一、React 全局状态方案对比
| 方案 | 学习成本 | 样板代码 | 体积 | 适用 |
|---|
| Context | 低 | 少 | 内置 | 低频共享(主题、登录态) |
| Redux(RTK) | 高 | 中 | 较大 | 大型项目、复杂状态流、团队规范 |
| Zustand | 低 | 极少 | ~1KB | 中小项目、快速上手 |
| Jotai / MobX | 中 | 少 | 小 | 细粒度状态、响应式偏好 |
选型建议:小项目用 Context 或 Zustand;大项目、面试常考用 Redux Toolkit;需求简单别上重方案。
二、Redux 核心极简使用(RTK)
2.1 安装与创建 Store
npm install @reduxjs/toolkit react-redux
import { createSlice } from "@reduxjs/toolkit";
const counterSlice = createSlice({
name: "counter",
initialState: { value: 0 },
reducers: {
increment: (state) => { state.value += 1; },
add: (state, action) => { state.value += action.payload; },
},
});
export const { increment, add } = counterSlice.actions;
export default counterSlice.reducer;
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./counterSlice";
export const store = configureStore({
reducer: { counter: counterReducer },
});
2.2 注入与使用
import { Provider } from "react-redux";
import { store } from "./store";
createRoot(document.getElementById("root")).render(
<Provider store={store}>
<App />
</Provider>
);
import { useDispatch, useSelector } from "react-redux";
import { increment } from "@/store/counterSlice";
function Counter() {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return <button onClick={() => dispatch(increment())}>计数:{count}</button>;
}
| 核心概念 | 作用 |
|---|
configureStore | 创建 store(自动集成 devtools 中间件) |
createSlice | 定义 state + reducers(自动生成 action) |
useSelector | 读取 state(订阅变化自动重渲染) |
useDispatch | 派发 action 触发更新 |
异步请求用 createAsyncThunk 写在 extraReducers 中;本处不展开,掌握上述四件套即可应对常规需求。
三、轻量方案 Zustand 快速上手
3.1 安装与定义 Store
npm install zustand
import { create } from "zustand";
export const useUserStore = create((set, get) => ({
user: null,
token: localStorage.getItem("token") || "",
login: (user) => {
set({ user, token: "token-" + Date.now() });
localStorage.setItem("token", "token-" + Date.now());
},
logout: () => set({ user: null, token: "" }),
}));
3.2 组件中使用
import { useUserStore } from "@/store/userStore";
function Profile() {
const user = useUserStore((s) => s.user);
const login = useUserStore((s) => s.login);
return (
<div>
{user ? <p>你好,{user.name}</p> : <button onClick={() => login({ name: "张三" })}>登录</button>}
</div>
);
}
3.3 Redux vs Zustand 快速对比
| 对比项 | Redux(RTK) | Zustand |
|---|
| 定义 | slice + reducer + action | create 一个函数搞定 |
| 读取 | useSelector | selector 函数 |
| 修改 | dispatch action | 直接调用 store 方法 |
| 学习成本 | 较高 | 极低 |
| 推荐场景 | 大型/复杂项目 | 中小项目、快速迭代 |
四、React 性能优化:memo、useMemo、useCallback
4.1 memo:组件级缓存
import { memo } from "react";
const ExpensiveList = memo(function ExpensiveList({ items }) {
return <ul>{items.map((i) => <li key={i.id}>{i.name}</li>)}</ul>;
});
注意:memo 是浅比较 props;父组件重渲染但 props 引用不变时,子组件不重渲染。
4.2 useMemo:值缓存
import { useMemo } from "react";
function Report({ list }) {
const total = useMemo(
() => list.reduce((sum, item) => sum + item.price, 0),
[list]
);
return <p>合计:{total}</p>;
}
4.3 useCallback:函数缓存
import { useCallback } from "react";
function Parent() {
const handleAdd = useCallback((id) => {
console.log("add", id);
}, []);
return <Child onAdd={handleAdd} />;
}
4.4 三件套区别与选择
| 工具 | 缓存对象 | 配合 memo 生效 | 典型场景 |
|---|
memo | 整个组件 | — | 重渲染昂贵的子组件 |
useMemo | 计算结果 | — | 大列表过滤、复杂运算 |
useCallback | 函数引用 | ✅ | 传给 memo 子组件的回调 |
4.5 什么时候不用优化
| 不必优化的情况 | 原因 |
|---|
| 组件很轻、渲染快 | 优化本身有开销(对比成本) |
| props 经常变化 | 缓存命中率低 |
| 提前优化的代码 | 先测量再优化("过早优化是万恶之源") |
五、总结
- 方案选型:Context(轻量低频)→ Zustand(中小项目)→ Redux(大型/面试);按复杂度选,别过度设计;
- Redux:
configureStore + createSlice + useSelector/useDispatch 四件套,Immer 允许直接改 state;
- Zustand:
create + set/get,selector 按需订阅,零样板;
- 优化:memo 缓存组件、useMemo 缓存值、useCallback 缓存函数,配合使用才有意义;
- 原则:先测量后优化,缓存依赖写全,避免过早优化。