React Context 详解

聊聊这个"全局变量"怎么用

先说结论:Context 就是为了解决"层层传 props 太麻烦"这个问题而生的。

想象一下:你有个数据要从顶层父组件传到第十层子组件,传统写法就得在中间九层都写上 props,即使它们根本不用这个数据——这就是所谓的 "prop drilling",烦死个人。

Context 就是来解决这个的。

怎么用?三步走

1. 创建 Context

const ThemeContext = React.createContext("light"); // 默认值

创建一个 Context 对象,里面包含 ProviderConsumer 两个组件。

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 有啥区别?

ContextRedux
本质依赖注入状态管理
功能传值传值 + 状态逻辑
更新优化自己做自带精细更新
学习成本稍高

一句话: Context 让数据"可以全局访问",Redux 教你怎么"高效地管理这个全局数据"。

总结

  • Context 解决的是"层层传 props 麻烦"的问题
  • 用法:createContext -> Provider -> useContext
  • 注意 value 变化会导致所有消费者重新渲染
  • 适合低频更新的全局数据(主题、用户、语言)
  • 复杂场景配合 Redux/Zustand 使用