React Context 详解
聊聊这个"全局变量"怎么用
先说结论:Context 就是为了解决"层层传 props 太麻烦"这个问题而生的。
想象一下:你有个数据要从顶层父组件传到第十层子组件,传统写法就得在中间九层都写上 props,即使它们根本不用这个数据——这就是所谓的 "prop drilling",烦死个人。
Context 就是来解决这个的。
怎么用?三步走
1. 创建 Context
const ThemeContext = React.createContext("light"); // 默认值
创建一个 Context 对象,里面包含 Provider 和 Consumer 两个组件。
2. 包上 Provider
<ThemeContext.Provider value="dark">
{/* 这里面的组件都能访问到 "dark" */}
<App />
</ThemeContext.Provider>
用 Provider 包裹需要访问数据的组件树,value 就是你要传的值。
value 变化时,所有消费这个 Context 的子组件都会重新渲染。
3. 子组件消费数据
两种方式:
方式一:useContext(推荐)
function Header() {
const theme = useContext(ThemeContext); // 直接拿到值
return <div className={theme}>我是头部</div>;
}
方式二:Consumer(老写法)
function Header() {
return <ThemeContext.Consumer>{(value) => <div className={value}>我是头部</div>}</ThemeContext.Consumer>;
}
现在基本都用 useContext,Consumer 了解就行。
性能问题要注意
Context 不是状态管理库,这点很重要。
更新机制
当 Provider 的 value 变了,所有消费这个 Context 的子组件都会重新渲染,不管它用没用那个变化的值。
所以如果你把一堆东西都塞进一个 Context:
<Context.Provider value={{ theme, setTheme, user, setUser, config, ... }}>
只要其中一个变了,所有子组件全重新渲染——这就炸了。
怎么优化?
1. 拆分 Context
别把所有东西都放一个 Context:
// 分成多个独立的 Context
const ThemeContext = React.createContext();
const UserContext = React.createContext();
const ConfigContext = React.createContext();
只关心主题的组件,只订阅 ThemeContext,user 变了跟它没关系。
2. 记忆化
传 value 时记得用 useMemo 稳定引用:
const value = useMemo(() => ({
theme,
setTheme
}), [theme, setTheme]);
<ThemeContext.Provider value={value}>
3. 配合状态管理库用
复杂应用里,Context 一般只用来做"依赖注入"——把 Redux、Zustand 的状态通过 Provider 传下去。状态管理本身还是交给专门的库来做。
什么时候用?
非常适合
- 主题:皮肤、颜色、字体大小
- 用户信息:当前用户、权限、登录状态
- 国际化:当前语言、翻译内容
- 全局配置:功能开关、AB 测试
这些都是"低频更新"的数据,用 Context 特别顺手。
不适合
- 高频更新的状态:比如表单输入、动画状态——用本地 state 更合适
- 想替代 Redux:Context 本质是"依赖注入",不是"状态管理"。它不帮你做不可变更新、中间件、时间旅行这些事
跟 Redux 有啥区别?
| Context | Redux |
|---|
| 本质 | 依赖注入 | 状态管理 |
| 功能 | 传值 | 传值 + 状态逻辑 |
| 更新优化 | 自己做 | 自带精细更新 |
| 学习成本 | 低 | 稍高 |
一句话: Context 让数据"可以全局访问",Redux 教你怎么"高效地管理这个全局数据"。
总结
- Context 解决的是"层层传 props 麻烦"的问题
- 用法:
createContext -> Provider -> useContext
- 注意 value 变化会导致所有消费者重新渲染
- 适合低频更新的全局数据(主题、用户、语言)
- 复杂场景配合 Redux/Zustand 使用