React 19 入门教程
Context 跨层级传递
本教程共 50 篇 · 第 23 篇 · 更新于 2026-07-29 · 约 7 分钟阅读
ReactContextcreateContextuseContextProvider
23. Context 跨层级传递
本节目标:理解 prop drilling 问题,掌握 Context 三件套,能跨多层组件传递数据。
prop drilling 是什么
状态提升解决了兄弟组件共享数据。但如果组件层级很深,数据要经过层层传递:
Page → Layout → Sidebar → Nav → UserAvatar
Page 持有 user 数据,UserAvatar 需要它。中间三个组件只是”搬运工”,被迫接收和传递它们不关心的 props。这就是 prop drilling(prop 逐级透传)。
function Page({ user }) {
return <Layout user={user} />;
}
function Layout({ user }) {
return <Sidebar user={user} />;
}
function Sidebar({ user }) {
return <Nav user={user} />;
}
function Nav({ user }) {
return <UserAvatar user={user} />;
}
每一层都要写 user={user},又丑又难维护。
Context 的解决方案
Context 像一条”隐形管道”,跳过中间层直达目标:
Page(提供数据)
├── Layout(不用管)
│ ├── Sidebar(不用管)
│ │ ├── Nav(不用管)
│ │ │ └── UserAvatar(直接读取)
三步使用 Context
第一步:创建 Context
// UserContext.js
import { createContext } from 'react';
export const UserContext = createContext(null);
createContext 的参数是默认值。没有匹配到 Provider 时,useContext 返回这个值。
第二步:提供 Context
在需要共享数据的父组件,用 Provider 包裹:
import { UserContext } from './UserContext';
function Page() {
const [user, setUser] = useState({ name: '张三', avatar: '🐱' });
return (
<UserContext value={user}>
<Layout />
</UserContext>
);
}
Provider 的 value
value可以是任何类型:对象、数组、函数、甚至另一个 state。
第三步:消费 Context
在任意后代组件里用 useContext 读取:
import { useContext } from 'react';
import { UserContext } from './UserContext';
function UserAvatar() {
const user = useContext(UserContext);
return <span>{user.avatar} {user.name}</span>;
}
Layout、Sidebar、Nav 都不用碰 user prop 了。
提供动态数据
Context 的 value 通常是 state,变化时所有消费者自动更新:
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
return (
<ThemeContext value={{ theme, setTheme }}>
{children}
</ThemeContext>
);
}
子组件既能读也能改:
function ThemeToggle() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
当前:{theme}
</button>
);
}
多个 Context 嵌套
一个组件可以消费多个 Context:
function Header() {
const user = useContext(UserContext);
const { theme } = useContext(ThemeContext);
const { locale } = useContext(LocaleContext);
return <header className={theme}>...</header>;
}
Provider 也可以任意嵌套:
<UserContext value={user}>
<ThemeContext value={theme}>
<LocaleContext value={locale}>
<App />
</LocaleContext>
</ThemeContext>
</UserContext>
Context 不是万能的
Context 有它的适用场景,不是什么东西都往里塞:
- 当前用户信息
- 主题/语言设置
- 认证状态
不适合频繁变化的数据(每次变化都重新渲染所有消费者),也不适合替代所有 props。
不要滥用 Context
如果数据只在父子两层之间传递,用 props 就行。Context 是为”跨很多层”设计的。
本节要点
- prop drilling:数据经过不相关的中间层传递
- Context 三件套:createContext → Provider → useContext
- Provider 的 value 通常是 state
- 适合跨多层的”全局”数据,不适合替代所有 props