createContext

createContext 允许你创建一个 context,组件可以提供或读取它。

const SomeContext = createContext(defaultValue)

参考

createContext(defaultValue)

在任何组件外部调用 createContext 来创建一个 context。

import { createContext } from 'react';

const ThemeContext = createContext('light');

查看更多示例。

参数

  • defaultValue:当读取 context 的组件上方树中没有匹配的 context 提供者时,你希望该 context 具有的值。如果你没有任何有意义的默认值,请指定 null。默认值是作为“最后手段”的回退值。它是静态的,且不会随着时间变化。

返回值

createContext 返回一个 context 对象。

context 对象本身不持有任何信息。 它表示其他组件读取或提供的是 哪一个 context。通常,你会在上方组件中使用 SomeContext 来指定 context 值,并在下方组件中调用 useContext(SomeContext) 来读取它。context 对象有几个属性:

  • SomeContext 允许你向组件提供 context 值。
  • SomeContext.Consumer 是一种替代且很少使用的读取 context 值的方式。
  • SomeContext.Provider 是在 React 19 之前提供 context 值的旧式方式。

SomeContext Provider

将你的组件包裹在一个 context provider 中,为其中所有组件指定该 context 的值:

function App() {
const [theme, setTheme] = useState('light');
// ...
return (
<ThemeContext value={theme}>
<Page />
</ThemeContext>
);
}

Note

从 React 19 开始,你可以将 <SomeContext> 作为 provider 来渲染。

在较旧版本的 React 中,请使用 <SomeContext.Provider>

Props

  • value:你希望传递给该 provider 内所有读取此 context 的组件的值,无论它们有多深。context 值可以是任意类型。在 provider 内部调用 useContext(SomeContext) 的组件会接收到其上方最近的对应 context provider 的 value

SomeContext.Consumer

useContext 出现之前,有一种较旧的读取 context 的方式:

function Button() {
// 🟡 旧式方式(不推荐)
return (
<ThemeContext.Consumer>
{theme => (
<button className={theme} />
)}
</ThemeContext.Consumer>
);
}

虽然这种旧方式仍然可用,但新编写的代码应该改为使用 useContext() 来读取 context:

function Button() {
// ✅ 推荐方式
const theme = useContext(ThemeContext);
return <button className={theme} />;
}

Props

  • children:一个函数。React 会使用与 useContext() 相同的算法确定当前 context 值,并以此调用你传入的函数,然后渲染该函数返回的结果。只要父组件中的 context 发生变化,React 还会重新运行此函数并更新 UI。

用法

创建 context

Context 允许组件在不显式传递 props 的情况下向深层传递信息

在任何组件外部调用 createContext 来创建一个或多个 context。

import { createContext } from 'react';

const ThemeContext = createContext('light');
const AuthContext = createContext(null);

createContext 返回一个 context 对象。组件可以通过将其传递给 useContext() 来读取 context:

function Button() {
const theme = useContext(ThemeContext);
// ...
}

function Profile() {
const currentUser = useContext(AuthContext);
// ...
}

默认情况下,它们接收到的值将是你在创建这些 context 时指定的 默认值。不过,这单独并没有什么用,因为默认值永远不会改变。

Context 很有用,因为你可以从组件中提供其他动态值:

function App() {
const [theme, setTheme] = useState('dark');
const [currentUser, setCurrentUser] = useState({ name: 'Taylor' });

// ...

return (
<ThemeContext value={theme}>
<AuthContext value={currentUser}>
<Page />
</AuthContext>
</ThemeContext>
);
}

现在,Page 组件以及其中的任何组件,无论多深,都将“看到”传入的 context 值。如果传入的 context 值发生变化,React 也会重新渲染读取该 context 的组件。

阅读更多关于读取和提供 context 的内容并查看示例。


从文件中导入和导出 context

通常,不同文件中的组件需要访问同一个 context。这就是为什么通常会将 context 声明在单独的文件中。然后你可以使用 export 语句 让其他文件可以使用该 context:

// Contexts.js
import { createContext } from 'react';

export const ThemeContext = createContext('light');
export const AuthContext = createContext(null);

在其他文件中声明的组件随后可以使用 import 语句来读取或提供这个 context:

// 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 value={theme}>
<AuthContext value={currentUser}>
<Page />
</AuthContext>
</ThemeContext>
);
}

这与导入和导出组件的工作方式类似。


故障排除

我找不到更改 context 值的方法

像这样的代码指定的是 context 的默认值:

const ThemeContext = createContext('light');

这个值永远不会改变。React 只有在上方找不到匹配的 provider 时才会使用这个值作为回退。

要让 context 随时间变化,添加 state 并将组件包裹在 context provider 中。