react的Context 跨层传值、优缺点、适用场景

React 的 Context(上下文)主要解决 跨层级组件传值(Props Drilling) 问题,即:父组件的数据需要经过很多层组件,最终传给深层子组件。


1. 什么是 Context

没有 Context:

javascript 复制代码
function App() {
  const theme = 'dark';

  return <Parent theme={theme} />;
}

function Parent({ theme }) {
  return <Child theme={theme} />;
}

function Child({ theme }) {
  return <GrandChild theme={theme} />;
}

function GrandChild({ theme }) {
  return <div>{theme}</div>;
}

数据:

复制代码
App → Parent → Child → GrandChild

即使 ParentChild 不使用 theme,也必须传。

这种叫:

复制代码
Props Drilling(属性穿透)

Context 用于解决这个问题。


2. Context 使用步骤(跨层传值)

React Context 核心 API:

scss 复制代码
createContext()
Provider
useContext()

第一步:创建 Context

创建:

javascript 复制代码
// ThemeContext.js

import { createContext } from "react";

export const ThemeContext = createContext();

默认值:

scss 复制代码
createContext("light");

如果 Provider 没包裹,会取默认值。


第二步:Provider 提供数据

根组件:

javascript 复制代码
import { ThemeContext } from "./ThemeContext";

function App() {

  const theme = "dark";

  return (
    <ThemeContext.Provider value={theme}>
      <Parent />
    </ThemeContext.Provider>
  );
}

Provider:

复制代码
提供共享数据

value:

复制代码
所有子组件可访问

第三步:子组件获取

深层组件:

javascript 复制代码
import { useContext } from "react";
import { ThemeContext } from "./ThemeContext";

function GrandChild() {

    const theme =
      useContext(ThemeContext);

    return <div>{theme}</div>;
}

输出:

复制代码
dark

即:

scss 复制代码
App
 ↓
Provider(value=dark)
 ↓
Parent
 ↓
Child
 ↓
GrandChild
 ↓
useContext()

直接拿值,不需要层层传。


完整例子

javascript 复制代码
import React,
{
 createContext,
 useContext,
 useState
}
from "react";

const UserContext =
createContext();

function App(){

 const [user,setUser]=
 useState("Tom");

 return(

<UserContext.Provider
value={{user,setUser}}
>

<Home/>

</UserContext.Provider>

 )
}

function Home(){

 return <Profile/>

}

function Profile(){

 const {user,setUser}
 =
 useContext(UserContext);

 return(

<>
<p>{user}</p>

<button
onClick={()=>
setUser("Jerry")
}
>

修改

</button>

</>

 )

}

结果:

点击按钮:

复制代码
Tom → Jerry

所有使用 Context 的组件都会更新。


3. Context 优点

(1)解决 Props Drilling

以前:

css 复制代码
App
↓
A
↓
B
↓
C
↓
D

需要:

ini 复制代码
<A user={user}/>
<B user={user}/>
...

Context:

scss 复制代码
useContext(UserContext)

直接取。

优势最大。


(2)全局共享状态

适合:

复制代码
用户信息
主题
权限
语言
Token
购物车

例如:

复制代码
theme
locale
loginUser

多个页面共用。


(3)代码更简洁

减少:

复制代码
props.xxx.xxx

改成:

scss 复制代码
useContext()

(4)避免层层维护

修改组件层级:

以前:

css 复制代码
App→A→B→C

变:

css 复制代码
App→X→A→B→C

props 全改。

Context 不需要。


4. Context 缺点

虽然方便,但不是状态管理库。


缺点1:性能问题(最大问题)

Context 数据变化:

ini 复制代码
value={{
 user,
 setUser
}}

user 改变:

复制代码
所有 useContext 的组件重新渲染

即使组件没用到变化的数据。

例如:

css 复制代码
UserContext

├── Header
├── Menu
├── Profile
└── Footer

修改:

复制代码
user.name

可能:

css 复制代码
Header 重渲染
Menu 重渲染
Footer 重渲染

性能下降。


优化:

scss 复制代码
const value =
useMemo(()=>({
 user,
 setUser
}),[user])

或拆多个 Context。



缺点2:不适合复杂状态

复杂业务:

复制代码
异步请求
缓存
分页
撤销
loading

Context 管理会混乱。

这时推荐:

  • Redux Toolkit
  • Zustand
  • MobX

缺点3:调试困难

Redux:

能看:

perl 复制代码
dispatch
state变化
时间旅行

Context:

没有。


缺点4:Provider 嵌套地狱

容易出现:

xml 复制代码
<AuthProvider>

<ThemeProvider>

<UserProvider>

<CartProvider>

<App/>

</CartProvider>

</UserProvider>

</ThemeProvider>

</AuthProvider>

可读性下降。


5. Context 适用场景

适合(推荐):

① 登录用户信息

复制代码
userInfo
token
role

② 主题切换

暗黑模式:

bash 复制代码
dark/light

最经典。


③ 多语言

复制代码
zh
en
jp

④ 权限控制

复制代码
isAdmin
permission

⑤ 全局配置

复制代码
API地址
系统配置

6. 不适合场景

不推荐:

大型复杂状态

例如:

复制代码
订单系统
即时聊天
性能平台
工作流系统

像你做的云鉴性能平台:

复制代码
性能查询
分页
筛选
缓存
异步请求
报告状态

更适合:

  • Redux Toolkit
  • Zustand
  • React Query + Context
  • MobX

而不是纯 Context。


7. Context 与 Redux 区别

对比 Context Redux
学习成本
跨层传值
状态管理 一般
性能优化 较差
调试
异步
大项目 不推荐 推荐

8. 一句话总结

Context 本质:

复制代码
跨组件共享数据机制

适合:

复制代码
主题
登录
权限
语言
配置

不适合:

复制代码
复杂全局状态管理

复杂项目优先考虑:

复制代码
Redux Toolkit
Zustand
React Query
相关推荐
用户13060956072311 小时前
elpis里程碑一的阶段性总结
前端
砍材农夫11 小时前
物联网 基于netty控制报文结构(发布与接收)
java·开发语言·前端·javascript·物联网
kevinten1011 小时前
说实话,我做了个"不务正业"的 AI:专门推荐冷门冒险地
前端
上单带刀不带妹11 小时前
Vue3 中 getCurrentInstance() 与 proxy 详解
前端·javascript·vue.js
Csvn11 小时前
前端 AI 应用:让浏览器运行机器学习模型
前端
妄念鹿11 小时前
记一次Uniapp的input输入框type为number时还能输入非数字
前端·javascript
ricardo197312 小时前
浏览器渲染流水线:从 HTML 到屏幕上的像素
前端·面试
明月_清风12 小时前
2026 前端生存指南:8 个正在重塑你职业生涯的技术趋势
前端·ai编程
ZTStory12 小时前
Volta 新一代 node 版本管理工具
前端·javascript·node.js