· 4 min read
React 状态管理
React
随着应用规模增长,状态管理极易变得越来越混乱。
React 状态管理是应用架构的核心,良好的状态管理能让代码更清晰、维护更轻松。
1. React 内置状态管理
1.1 useState:局部状态
function Counter() {
const [count, setCount] = useState(0);
const [user, setUser] = useState({ name: '张三', age: 25 });
return (
<div>
<p>计数: {count}</p>
<button onClick={() => setCount(c => c + 1)}>增加</button>
<button onClick={() => setUser({ ...user, age: user.age + 1 })}>长大</button>
</div>
);
}
1.2 useReducer:复杂状态
function todoReducer(state, action) {
switch (action.type) {
case 'ADD':
return [...state, action.payload];
case 'TOGGLE':
return state.map(todo =>
todo.id === action.payload ? { ...todo, done: !todo.done } : todo
);
case 'DELETE':
return state.filter(todo => todo.id !== action.payload);
default:
return state;
}
}
function TodoApp() {
const [todos, dispatch] = useReducer(todoReducer, []);
return (
<div>
<button onClick={() => dispatch({ type: 'ADD', payload: { id: Date.now(), text: '新任务', done: false }})}>
添加
</button>
</div>
);
}
1.3 Context:跨组件共享
const ThemeContext = createContext();
const UserContext = createContext();
function App() {
const [theme, setTheme] = useState('light');
const [user, setUser] = useState({ name: '张三', id: 1 });
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<UserContext.Provider value={user}>
<Layout />
</UserContext.Provider>
</ThemeContext.Provider>
);
}
function Layout() {
const { theme, setTheme } = useContext(ThemeContext);
const user = useContext(UserContext);
return (
<div className={theme}>
<h1>欢迎, {user.name}</h1>
<button onClick={() => setTheme(t => t === 'light' ? 'dark' : 'light')}>
切换主题
</button>
</div>
);
}
2. 状态管理最佳实践
2.1 最小化状态
// ❌ 避免:冗余状态
function BadExample() {
const [firstName, setFirstName] = useState('张');
const [lastName, setLastName] = useState('三');
const fullName = firstName + lastName; // 这不需要是状态
return <div>{fullName}</div>;
}
// ✅ 推荐:计算属性
function GoodExample() {
const [user, setUser] = useState({ firstName: '张', lastName: '三' });
const fullName = `${user.firstName}${user.lastName}`; // 通过计算得到
return <div>{fullName}</div>;
}
2.2 状态提升
// ❌ 避免:状态分散
function Parent() {
return (
<>
<ChildA />
<ChildB />
</>
);
}
// ✅ 推荐:提升到共同父组件
function Parent() {
const [shared, setShared] = useState('');
return (
<>
<ChildA value={shared} onChange={setShared} />
<ChildB value={shared} />
</>
);
}
2.3 不可变数据
// ❌ 避免:直接修改状态
function badReducer(state, action) {
switch (action.type) {
case 'ADD':
state.push(action.payload); // 直接修改!
return state;
}
}
// ✅ 推荐:创建新数据
function goodReducer(state, action) {
switch (action.type) {
case 'ADD':
return [...state, action.payload]; // 新数组
case 'UPDATE':
return state.map(item =>
item.id === action.payload.id ? { ...item, ...action.payload } : item
);
}
}
3. 第三方状态管理
3.1 Redux
// store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
export const store = configureStore({
reducer: {
counter: counterReducer,
},
});
// counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => { state.value += 1; },
decrement: (state) => { state.value -= 1; },
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
// Component.jsx
import { useSelector, useDispatch } from 'react-redux';
import { increment } from './counterSlice';
function Counter() {
const count = useSelector(state => state.counter.value);
const dispatch = useDispatch();
return (
<div>
<p>计数: {count}</p>
<button onClick={() => dispatch(increment())}>增加</button>
</div>
);
}
3.2 Zustand(轻量级)
import { create } from 'zustand';
const useStore = create(set => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 })),
decrement: () => set(state => ({ count: state.count - 1 })),
}));
function Counter() {
const { count, increment, decrement } = useStore();
return (
<div>
<p>计数: {count}</p>
<button onClick={decrement}>减少</button>
<button onClick={increment}>增加</button>
</div>
);
}
3.3 方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| useState | 简单、无依赖 | 状态分散 | 小型应用 |
| useReducer | 逻辑集中 | 学习成本 | 中型应用 |
| Context | 跨组件共享 | 容易过度使用 | 全局配置 |
| Redux | 强大工具链 | 样板代码多 | 大型应用 |
| Zustand | 轻量简单 | 社区较小 | 中小型应用 |
4. 状态管理模式
4.1 原子化状态(Jotai)
import { atom } from 'jotai';
import { useAtom } from 'jotai';
const countAtom = atom(0);
const doubledAtom = atom((get) => get(countAtom) * 2);
function Counter() {
const [count, setCount] = useAtom(countAtom);
const [doubled] = useAtom(doubledAtom);
return (
<div>
<p>计数: {count}</p>
<p>翻倍: {doubled}</p>
<button onClick={() => setCount(c => c + 1)}>增加</button>
</div>
);
}
4.2 信号(Signals)
import { signal, computed } from '@preact/signals-react';
const count = signal(0);
const doubled = computed(() => count.value * 2);
function Counter() {
return (
<div>
<p>计数: {count}</p>
<p>翻倍: {doubled}</p>
<button onClick={() => count.value++}>增加</button>
</div>
);
}
5. 总结
选择状态管理方案的建议:
- 小型应用: useState + useReducer 足够
- 中型应用: Context + 自定义 Hook,或 Zustand
- 大型应用: Redux Toolkit 或其他成熟方案
核心原则:最小化状态、单一数据源、不可变更新。