createContext
允许你创建一个上下文,组件可以提供或读取该上下文。
const SomeContext = createContext(defaultValue)
参考
createContext(defaultValue)
在任何组件之外调用createContext
以创建上下文。
import { createContext } from 'react';
const ThemeContext = createContext('light');
参数
defaultValue
:当在读取上下文的组件上方树中没有匹配的上下文提供程序时,你想让上下文具有的值。如果你没有任何有意义的默认值,请指定null
。默认值旨在作为“最后手段”回退。它是静态的,不会随着时间的推移而改变。
返回
createContext
返回一个上下文对象。
上下文对象本身不保存任何信息。它表示其他组件读取或提供的哪个上下文。通常,你会在上面的组件中使用SomeContext.Provider
来指定上下文值,并在下面的组件中调用useContext(SomeContext)
来读取它。上下文对象有一些属性
SomeContext.Provider
允许你为组件提供上下文值。SomeContext.Consumer
是一种替代方法,很少使用,用于读取上下文值。
SomeContext.Provider
将你的组件包装到上下文提供程序中,以指定此上下文对于所有内部组件的值
function App() {
const [theme, setTheme] = useState('light');
// ...
return (
<ThemeContext.Provider value={theme}>
<Page />
</ThemeContext.Provider>
);
}
属性
value
:你想传递给所有读取此上下文中的组件的值,无论嵌套多深。上下文的值可以是任何类型。在提供程序内部调用useContext(SomeContext)
的组件会接收到其上方最内层对应上下文提供程序的value
。
SomeContext.Consumer
在useContext
出现之前,有一种读取上下文的老方法。
function Button() {
// 🟡 Legacy way (not recommended)
return (
<ThemeContext.Consumer>
{theme => (
<button className={theme} />
)}
</ThemeContext.Consumer>
);
}
虽然这种老方法仍然有效,但是新编写的代码应该使用useContext()
来读取上下文:
function Button() {
// ✅ Recommended way
const theme = useContext(ThemeContext);
return <button className={theme} />;
}
属性
children
:一个函数。React 将调用你传入的函数,并使用与useContext()
相同的算法确定的当前上下文值,并渲染你从这个函数返回的结果。每当来自父组件的上下文发生变化时,React 也会重新运行此函数并更新 UI。
用法
创建上下文
上下文允许组件深度传递信息,无需显式传递属性。
调用createContext
(在任何组件之外)以创建一个或多个上下文。
import { createContext } from 'react';
const ThemeContext = createContext('light');
const AuthContext = createContext(null);
createContext
返回一个上下文对象。组件可以通过将其传递给useContext()
来读取上下文。
function Button() {
const theme = useContext(ThemeContext);
// ...
}
function Profile() {
const currentUser = useContext(AuthContext);
// ...
}
默认情况下,它们接收到的值将是创建上下文时指定的默认值。但是,就其本身而言,这并没有用,因为默认值永远不会改变。
上下文之所以有用,是因为你可以从你的组件提供其他动态值:
function App() {
const [theme, setTheme] = useState('dark');
const [currentUser, setCurrentUser] = useState({ name: 'Taylor' });
// ...
return (
<ThemeContext.Provider value={theme}>
<AuthContext.Provider value={currentUser}>
<Page />
</AuthContext.Provider>
</ThemeContext.Provider>
);
}
现在Page
组件及其内部的任何组件(无论嵌套多深)都将“看到”传递的上下文值。如果传递的上下文值发生变化,React 也会重新渲染读取上下文的组件。
从文件中导入和导出上下文
通常,不同文件中的组件需要访问相同的上下文。这就是在单独的文件中声明上下文很常见的原因。然后,你可以使用export
语句使上下文可用于其他文件。
// Contexts.js
import { createContext } from 'react';
export const ThemeContext = createContext('light');
export const AuthContext = createContext(null);
然后,在其他文件中声明的组件可以使用import
语句来读取或提供此上下文。
// Button.js
import { ThemeContext } from './Contexts.js';
function Button() {
const theme = useContext(ThemeContext);
// ...
}
// App.js
import { ThemeContext, AuthContext } from './Contexts.js';
function App() {
// ...
return (
<ThemeContext.Provider value={theme}>
<AuthContext.Provider value={currentUser}>
<Page />
</AuthContext.Provider>
</ThemeContext.Provider>
);
}
这与导入和导出组件类似。
故障排除
我找不到更改上下文值的方法
像这样的代码指定了默认上下文值
const ThemeContext = createContext('light');
此值永不更改。只有当 React 找不到上面的匹配提供程序时,才会使用此值作为后备。
要使上下文随时间变化,添加状态并将组件包装在上下文提供程序中。