React 本身并不强制你使用 Redux 等外部库,但借助 useContext + useReducer,就能实现“小型 Redux”的全局状态管理架构。
它的特点:
- 全局状态共享
- 集中式更新逻辑(类似 Redux)
- 组件无须一层层 props 传递
- 内置 Hooks,不依赖第三方库
- 可拆分模块,维护清晰
下面带你从原理到实战一步搞定。
1. 为什么要用 useContext + useReducer
🔥 适用场景
- 全局共享状态(用户信息、主题设置、语言等)
- 多组件都需要读写同一份数据
- 状态更新逻辑复杂(大量 if/else)
- 希望将逻辑与 UI 分离(更清晰、更可维护)
❌ useState 不适合做全局共享状态
因为:
- 需要 props 层层传递
- 状态逻辑散落在多个组件中
- 难以维护
2. 核心架构图(非常重要)
[ Context Provider ]
|
V
[ useReducer ] ------> reducer.js(更新逻辑)
|
V
[ 全局状态 state ]
|
V
[ 任何子组件 useContext ] ——(读取/dispatch)
本质就是:
useContext 做“全局共享”,useReducer 做“统一更新逻辑”。
3. 实战:搭建一个全局用户管理 Store
以管理用户登录状态为例:
Step 1:定义 reducer(action + 更新逻辑)
store/userReducer.js
export const initialState = {
user: null,
isLogin: false
};
export function userReducer(state, action) {
switch (action.type) {
case "LOGIN":
return {
...state,
user: action.payload,
isLogin: true
};
case "LOGOUT":
return {
...state,
user: null,
isLogin: false
};
default:
return state;
}
}
Step 2:创建 Context Provider(状态容器)
store/UserContext.js
import { createContext, useReducer } from "react";
import { userReducer, initialState } from "./userReducer";
export const UserContext = createContext();
export function UserProvider({ children }) {
const [state, dispatch] = useReducer(userReducer, initialState);
return (
<UserContext.Provider value={{ state, dispatch }}>
{children}
</UserContext.Provider>
);
}
这一步很核心:
state:全局状态dispatch:提交 action- 子组件通过 Context 获取
Step 3:在应用入口包裹 Provider
index.js 或 App.js
import { UserProvider } from "./store/UserContext";
export default function App() {
return (
<UserProvider>
<HomePage />
</UserProvider>
);
}
Step 4:任意子组件使用全局状态
读取用户信息
const { state } = useContext(UserContext);
return <div>当前用户:{state.user?.name}</div>;
登录/登出(使用 dispatch)
const { dispatch } = useContext(UserContext);
function login() {
dispatch({
type: "LOGIN",
payload: { name: "Tom", id: 1 }
});
}
function logout() {
dispatch({ type: "LOGOUT" });
}
4. 分模块:适合中大型应用
如果状态很多,可以拆多个 store:
/store
/user
userReducer.js
UserContext.js
/theme
themeReducer.js
ThemeContext.js
每个模块独立,可组合使用。
5. 注意事项
⚠ 避免 Context 频繁刷新
Provider 的 value 变化会导致所有子组件 rerender。
如果你状态频繁更新:
建议拆成多个 Context:
- UserContext
- ThemeContext
- SettingsContext
6. useContext + useReducer vs Redux
| 点 | useContext + useReducer | Redux |
|---|---|---|
| 复杂度 | 简单 | 中/高 |
| 依赖 | 无 | 需要安装 |
| 大型项目 | 一般 | ✔ 最适合 |
| 调试工具 | 少 | ✔ Redux DevTools |
| 代码架构 | 自由 | 严格规范 |
总结
小项目 → useContext + useReducer
大项目 → Redux Toolkit