状态管理
一、是什么
管理组件之间共享数据的方案。
二、方案对比
1. React 内置
React Context + useState / useReducer 是一个内置于 React 的轻量级状态管理方案。
-
核心思路
创建一个 Context 对象(React.createContext)
在顶层组件(如 App)中定义状态和更新函数
将这些值通过
Context.Provider的value向下传递任意子组件通过 useContext(Context) 获取状态和更新函数,实现“跨层级”读写
-
简单示例:(使用 useState)
// 1. 创建 Context import React, { createContext, useState, useContext } from 'react'; const ThemeContext = createContext(); // 2. 创建 Provider 组件,管理状态 function ThemeProvider({ children }) { const [theme, setTheme] = useState('light'); const toggleTheme = () => { setTheme(prev => (prev === 'light' ? 'dark' : 'light')); }; // 将状态和方法放入 value return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> {children} </ThemeContext.Provider> ); } // 3. 自定义 Hook 方便使用 function useTheme() { return useContext(ThemeContext); } // 4. 子组件使用 function ThemedButton() { const { theme, toggleTheme } = useTheme(); return ( <button onClick={toggleTheme} style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff' }} > 当前主题:{theme},点击切换 </button> ); } function Toolbar() { return <ThemedButton />; // 中间可以嵌套任意深层组件 } // 5. 顶层 App 使用 Provider export default function App() { return ( <ThemeProvider> <Toolbar /> </ThemeProvider> ); } -
复杂状态管理:待办事项(使用 useReducer + Context)
import React, { createContext, useReducer, useContext } from 'react'; // 1. 定义 state 结构和 reducer const initialState = { todos: [], nextId: 1 }; function todoReducer(state, action) { switch (action.type) { case 'ADD_TODO': return { ...state, todos: [...state.todos, { id: state.nextId, text: action.payload, completed: false }], nextId: state.nextId + 1 }; case 'TOGGLE_TODO': return { ...state, todos: state.todos.map(todo => todo.id === action.payload ? { ...todo, completed: !todo.completed } : todo ) }; case 'DELETE_TODO': return { ...state, todos: state.todos.filter(todo => todo.id !== action.payload) }; default: return state; } } // 2. 创建 Context const TodoContext = createContext(); // 3. Provider 组件:整合 reducer 并向下传递状态和 dispatch function TodoProvider({ children }) { const [state, dispatch] = useReducer(todoReducer, initialState); // 也可以把 dispatch 单独传递,也可以封装成 action 函数再传递,通常直接传递 dispatch 更灵活 return ( <TodoContext.Provider value={{ state, dispatch }}> {children} </TodoContext.Provider> ); } // 4. 自定义 Hook function useTodos() { return useContext(TodoContext); } // 5. 展示和操作组件的示例 function TodoList() { const { state, dispatch } = useTodos(); return ( <ul> {state.todos.map(todo => ( <li key={todo.id} style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}> <span onClick={() => dispatch({ type: 'TOGGLE_TODO', payload: todo.id })}> {todo.text} </span> <button onClick={() => dispatch({ type: 'DELETE_TODO', payload: todo.id })}> 删除 </button> </li> ))} </ul> ); } function AddTodo() { const { dispatch } = useTodos(); const [text, setText] = React.useState(''); const handleSubmit = (e) => { e.preventDefault(); if (text.trim()) { dispatch({ type: 'ADD_TODO', payload: text }); setText(''); } }; return ( <form onSubmit={handleSubmit}> <input value={text} onChange={(e) => setText(e.target.value)} /> <button type="submit">添加</button> </form> ); } // 6. 顶层 App export default function App() { return ( <TodoProvider> <AddTodo /> <TodoList /> </TodoProvider> ); }
2. 外部库
-
Redux(最经典)
Redux 核心思想:单一 store、只读 state、reducer 纯函数修改。现代写法使用 @reduxjs/toolkit 和 react-redux,极大简化了样板代码。
npm install @reduxjs/toolkit react-redux// store.js import { configureStore, createSlice } from '@reduxjs/toolkit'; // 创建 slice(包含 state + reducer) const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 }, reducers: { increment: (state) => { state.value += 1 }, // 允许写“可变”代码(内部用 Immer) decrement: (state) => { state.value -= 1 }, addBy: (state, action) => { state.value += action.payload } } }); export const { increment, decrement, addBy } = counterSlice.actions; export const store = configureStore({ reducer: { counter: counterSlice.reducer } });// App.js import React from 'react'; import { Provider, useSelector, useDispatch } from 'react-redux'; import { store, increment, decrement, addBy } from './store'; function Counter() { const count = useSelector(state => state.counter.value); const dispatch = useDispatch(); return ( <div> <h1>{count}</h1> <button onClick={() => dispatch(increment())}>+1</button> <button onClick={() => dispatch(decrement())}>-1</button> <button onClick={() => dispatch(addBy(5))}>+5</button> </div> ); } export default function App() { return ( <Provider store={store}> <Counter /> </Provider> ); } -
Zustand(极简现代)
Zustand 不需要 Provider,直接创建 store,Hooks 式使用,代码非常少。
npm install zustandimport { create } from 'zustand'; // 创建 store const useCounterStore = create((set) => ({ count: 0, increment: () => set((state) => ({ count: state.count + 1 })), decrement: () => set((state) => ({ count: state.count - 1 })), addBy: (amount) => set((state) => ({ count: state.count + amount })), })); function Counter() { // 选择性订阅,避免不必要的重渲染 const { count, increment, decrement, addBy } = useCounterStore(); return ( <div> <h1>{count}</h1> <button onClick={increment}>+1</button> <button onClick={decrement}>-1</button> <button onClick={() => addBy(5)}>+5</button> </div> ); } export default function App() { return <Counter />; // 无需 Provider! } -
MobX(响应式可变状态)
MobX 通过
@observable和@action让状态变得“可观察”,任何组件只要 observer 包裹,就会自动追踪依赖并更新。npm install mobx mobx-react-liteimport { makeAutoObservable } from 'mobx'; import { observer } from 'mobx-react-lite'; import React from 'react'; // 创建 store 类 class CounterStore { count = 0; constructor() { makeAutoObservable(this); // 自动使属性可观察,方法变成 action } increment() { this.count += 1; } decrement() { this.count -= 1; } addBy(amount) { this.count += amount; } } const counterStore = new CounterStore(); // 组件用 observer 包裹,自动响应变化 const Counter = observer(() => { return ( <div> <h1>{counterStore.count}</h1> <button onClick={() => counterStore.increment()}>+1</button> <button onClick={() => counterStore.decrement()}>-1</button> <button onClick={() => counterStore.addBy(5)}>+5</button> </div> ); }); export default function App() { return <Counter />; }
对比
| 库 | 代码量 | 需要 Provider | 心智模型 | 适合场景 |
|---|---|---|---|---|
| Redux | 中等 | 是 | 单向数据流 + 纯函数 | 大型应用,严格可控 |
| Zustand | 极少 | 否 | 简单 Hooks | 中小型、快速开发 |
| MobX | 少 | 否 | 响应式可变状态 | 复杂对象、领域模型 |
三、核心原理
1. 发布订阅
store → subscribe → 更新组件
2. 单向数据流
action → reducer → state → UI
四、实践
- 小项目:Context + Hooks
- 大项目:Zustand / Redux Toolkit