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

即使 Parent 和 Child 不使用 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
相关推荐
沙蒿同学8 小时前
不引 Ghostscript:我用纯 Go 给 PDF 做了一场「压缩手术」
前端·后端·github
变与不变8068 小时前
jQuery细节以及使用应用场景
前端·javascript·jquery
SailingCoder10 小时前
【封闭结束1】端到端交付:Agent 一次请求如何走完全链路
前端·安全·ai·面试·agent·harness
风骏时光牛马12 小时前
AI多模块协同自动化工作流
前端
zhangminghuan12 小时前
前端面试应对技巧
前端·面试·职场和发展
计算机魔术师13 小时前
潜伏14年的PHP致命洞,AI跑两天就交卷了
前端
IT_陈寒13 小时前
Vue的这个响应式陷阱我居然现在才发现
前端·人工智能·后端
Python自动化直播14 小时前
智能脚本批量管理拆开看:导入、导出、重写、试听
前端·python·ai·秒播
开开心心就好14 小时前
发票信息录入太麻烦?离线工具一键转表格
运维·服务器·前端·pdf·ocr·maven·intellij-idea