Open yaogengzhu opened 2 years ago
useContext 和 Context
useContext
接收一个context对象 React.createContext
的返回值 并返回该context的当前值,当前的context值由上层组件中距离当前组件最近的
useContext
的参数必须是context对象本身
context = React.createContext({})
const { } = useContext(context)
Context
提供了一个无需为每层组件手动添加props,就能在组件进行数据传递。
Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递props
API
React.createContext
const MyContext = React.createContext(defaultValue);
Context.Provider
<MyContext.Provider value={/* 某个值 */}>
Context.Consumer
<MyContext.Consumer>
{value => /* 基于 context 值进行渲染*/}
</MyContext.Consumer>
Context.displayName
用来在 React DevTools 使用该字符串来确定context的要显示的内容
const MyContext = React.createContext(/* some value */);
MyContext.displayName = 'MyDisplayName';
<MyContext.Provider> // "MyDisplayName.Provider" 在 DevTools 中
<MyContext.Consumer> // "MyDisplayName.Consumer" 在 DevTools 中
实践 --- 国际化
import { createContext } from 'react';
export type ILang = 'zh-CN' | 'en-US'
type IContentProps = {
lang: ILang;
setLang: (value: ILang) => void;
};
export const GlobalContext = createContext<IContentProps>({
lang: 'zh-CN',
setLang: () => {}
});
const App = () => {
useTheme();
const [lang, setLang] = useState<ILang>('zh-CN'); // 后期做一个本地持久化
const contextValue = {
lang,
setLang,
};
const locale = useMemo(() => {
switch (lang) {
case 'zh-CN':
return zhCN;
case 'en-US':
return enUS;
default:
return zhCN;
}
}, [lang]);
return (
<ConfigProvider locale={locale}>
<GlobalContext.Provider value={contextValue}>
<BrowserRouter>
<Suspense fallback={<Loading />}>
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/*" element={<Home />} />
</Routes>
</Suspense>
</BrowserRouter>
</GlobalContext.Provider>
</ConfigProvider>
);
};
使用
const { lang, i18n, setLang } = useLocale();
...
const changeLanguage = (lang: string) => {
if (lang === 'zh-CN') {
Message.info('语言切换至 zh-CN');
setLang('zh-CN');
} else {
Message.info('Language switch to en-US');
setLang && setLang('en-US');
}
};
const languageList = (
<Menu onClickMenuItem={changeLanguage} defaultSelectedKeys={[lang]}>
<Menu.Item key="zh-CN">中文</Menu.Item>
<Menu.Item key="en">English</Menu.Item>
</Menu>
);
...
补充文档: 对上面文档进行补充:
react 文档
如何访问另一个组件的DOM节点 Accessing another component’s DOM nodes
import { useRef, forwardRef } from 'react'
import TodoList from './components/TodoList'
const MyInput = forwardRef((props, ref: React.LegacyRef<HTMLInputElement>) => {
return <input {...props} ref={ref} />
})
const App = () => {
const inputRef: React.LegacyRef<HTMLInputElement> = useRef(null)
const focusEvent = () => {
inputRef.current?.focus()
}
return (
<div title="test" data-test="container">
<TodoList />
<MyInput ref={inputRef} />
<button onClick={focusEvent}>按钮</button>
</div>
)
}
export default App
forwardRef 与 useImperativeHandle
React.forwardRef
会创建一个React组件,这个组件能接受的ref
属性转发到其他组件树下的另外一个组件。两种应用场景
React.forwardRef
接受渲染函数作为参数, React将props 和 ref 作为参数来调用此函数.。此函数应返回React节点。useImperativeHandle
可以让你正在使用ref
时自定义暴露给父组件的实例值。这个使用应该与React.forwardRef
一起使用。实际应用场景
ant-design-mobile
组件库中Dialog
方法中 代码地址