react中的Context 为什么会导致性能问题? 在 React 中Context本身不是性能问题但Context 的更新机制容易导致不必要的组件重新渲染这也是大家常说的“Context 导致性能问题”的根本原因。Context 的工作原理假设有这样一个 Contextconst UserContext React.createContext(null); function App() { const [user, setUser] useState({ name: Tom, age: 18 }); return ( UserContext.Provider value{user} Header / Content / Footer / /UserContext.Provider ); }Header和Content中使用了 Contextfunction Header() { const user useContext(UserContext); return div{user.name}/div; } function Content() { const user useContext(UserContext); return div{user.age}/div; }问题 1Context 更新会导致所有消费者重新渲染当执行setUser({ name: Tom, age: 19 });React 会发现value{user}发生了变化。于是Header Content所有调用了useContext(UserContext)的组件都会重新执行。即使Header只依赖name而这次更新的只是ageHeader 仍然会重新渲染。示例function Header() { console.log(Header render); const user useContext(UserContext); return div{user.name}/div; } function Content() { console.log(Content render); const user useContext(UserContext); return div{user.age}/div; }点击setUser({ ...user, age: user.age 1 });控制台Header render Content render两者都会执行。问题 2React.memo 对 Context 无效很多人以为export default React.memo(Header);就能解决。实际上const user useContext(UserContext);Context 更新时React.memo不会阻止重新渲染。因为 Context 更新属于Provider - Consumer的直接通知机制。例如const Header React.memo(() { const user useContext(UserContext); return div{user.name}/div; });仍然会重新执行。问题 3Provider 每次创建新对象很多项目会这样写UserContext.Provider value{{ user, updateUser, }} 这里{ user, updateUser, }每次渲染都会创建新对象。即使user没有变化。React 仍认为value ! oldValue于是所有 Consumer 更新。错误示例function App() { const [count, setCount] useState(0); return ( UserContext.Provider value{{ name: Tom, }} Child / /UserContext.Provider ); }每次setCount(...)都会产生{ name: Tom }新引用。导致Child重新渲染。解决方案 1useMemo 缓存 valueconst contextValue useMemo( () ({ user, updateUser, }), [user] ); UserContext.Provider value{contextValue}这样只有user变化时才通知 Consumer。解决方案 2拆分 Context不要把所有状态放一个 Context。不推荐{ user, theme, language, permission, menu, }只要一个字段变化所有 Consumer 更新推荐UserContext.Provider ThemeContext.Provider LanguageContext.Provider例如const UserContext createContext(); const ThemeContext createContext();修改主题setTheme(...)不会影响用户信息组件。解决方案 3Context SelectorRedux 的核心优化思想。例如const name useContextSelector( UserContext, state state.name );修改age时name不会更新。常见库use-context-selectorzustandredux例如import { useContextSelector } from use-context-selector; const name useContextSelector( UserContext, v v.name );只有name变化时才渲染。解决方案 4使用 Zustand / Redux大型项目里Context更适合主题 Theme国际化 i18n登录用户信息配置项不适合高频更新状态大量组件共享状态例如鼠标位置 实时表单 聊天消息 表格状态这些场景使用ZustandRedux Toolkit通常性能更好。React Context 性能问题总结原因说明Consumer 全量通知Context 更新时所有 Consumer 都会重新渲染无细粒度订阅无法只监听某个字段React.memo 无效Context 更新会绕过 memovalue 对象变化新引用会触发更新单一大 Context一个字段变化影响全部组件一句话概括Context 的性能问题不在于读取useContext而在于Provider 的value一旦引用变化所有消费该 Context 的组件都会重新渲染无法像 Redux/Zustand 那样做到字段级订阅。