React context 是 React 提供的基本工具,用于在组件间共享状态。
本文介绍 React context 的基本用法。

什么是 React Context?
React context 允许我们不对组件树的每层组件手动添加 props 来传递数据的情况下,在组件间共享数据。它能让我们更容易的跨组件共享状态。
什么时候使用 React Context?
当某些状态可能在任何组件中都会被使用时,React context 是非常有用的。
比如:
- UI 主题状态(亮暗模式、用户定制的 UI 风格等)
- 当前会话的用户数据(用户名、头像等)
- 当前语言或区域
React context 会让项目里的任何组件都能轻松访问到这些状态。
React context 解决了什么问题?
React context 帮我们解决了 props drilling 问题。
Props drilling 是指状态以 props 的形式从 React 组件树中一直往下传递, 但中间层组件并不需要这些 props, 只是做一个向下转发,这种情况就叫做 props drilling。
下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| export default function App() { const [user, setUser] = useState({ name: 'Eson', age: 18 });
return ( <Header user={user}> ) }
const Header = ({ user }) => { return ( <> <Menu user={user}> </> ) }
|
你可以看到,Header 组件中的 user 状态是通过 props drilling 来获取的。App 的直接子组件 Header 并不需要 user 状态,它只是做一个向下转发。
怎么使用 React context?
使用 React context API React.createContext 方法创建 context
1 2 3
| const UserContext = React.createContext({ name: "Eson", age: 18 }); // 第一个参数是默认值
export default UserContext;
|
使用 React context 的 Provider 组件包裹你的组件
1 2 3 4 5 6 7 8 9 10 11 12
| import React, { useState } from "react"; import UserContext from "userContext.js";
const App = () => { const [user, setUser] = useState({ name: "Eson", age: 18 });
return ( <UserContext.Provider value={user}> <Header /> </UserContext.Provider> ); };
|
使用 React context 的 Consumer 组件获取 context 状态,提供给使用状态的组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import React from "react"; import UserContext from "userContext.js";
const Header = () => { return <Menu />; };
const Menu = () => { return ( <UserContext.Consumer> {(user) => ( <div> {user.name} <button>退出</button> </div> )} </UserContext.Consumer> ); };
|
上面的示例代码中,被 UserContext.Provider 组件包裹的组件树才可以通过 UserContext.Consumer 组件来获取用户的状态。
Context hook
随着 React 带来了 Hooks,我们可以使用 useContext 来获取 context 状态。
`useContext`` 接收一个 context 对象,返回一个 context 的值。它使我们的组件更加简洁,并允许我们创建自己的自定义钩子。
1 2 3 4 5 6 7 8 9 10 11 12 13
| import React, { useContext } from "react"; import UserContext from "userContext.js";
const Menu = () => { const user = useContext(UserContext);
return ( <div> {user.name} <button>退出</button> </div> ); };
|
使用 React context 的注意事项
解决 props drilling 的问题,React context 可以解决,但是它不是一个好的选择。第一是因为这会让组件的复用性变差,第二是 context 状态如果是一个对象,更新的时候会导致所有使用这个 context 的组件重新渲染,即使仅使用了未更新的属性值。
我们也可以更好组合我们的组件来解决这个问题,比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import React from "react";
const App = () => { const [user, setUser] = useState({ name: "Eson", age: 18 });
return ( <Header> <Menu user={user} /> </Header> ); };
const Header = ({ children }) => { return <header>{children}</header>; };
const Menu = ({ user }) => { return ( <div> {user.name} <button>退出</button> </div> ); };
|