React 状态管理库相关收录
React 状态管理库相关收录
本文档总结了当前主流 React 状态管理库的核心特性、优缺点及使用模式,方便快速查阅和选型。
概览与选型指南
快速选型矩阵
| 库名 | 核心思想 | 适用场景 | 
|---|---|---|
| Zustand | 极简单一 Store | 中小型项目、追求开发效率 | 
| Redux (RTK) | 严格单向数据流 | 大型复杂应用、强可维护性 | 
| Jotai | 原子化状态 | 复杂组件状态、细粒度控制 | 
| MobX | 响应式编程 | 中大型项目、熟悉响应式编程 | 
| Context API | 内置状态传递 | 低频更新的全局状态 | 
选型考虑因素
- 
项目规模 - 小型项目:Zustand、Jotai、Context API
- 大型项目:Redux Toolkit、MobX
 
- 
团队熟悉度 - 熟悉 Flux 架构:Redux
- 偏好响应式:MobX
- 追求简洁:Zustand、Jotai
 
- 
性能要求 - 高频更新:Zustand、Jotai、MobX
- 低频更新:Context API
 
- 
TypeScript 支持 - 优秀:Zustand、Redux Toolkit、Jotai
- 良好:MobX
 
Zustand
核心特性
- ✅ 极简 API,学习成本低
- ✅ 无需 Provider 包裹
- ✅ 基于 Hook 的使用方式
- ✅ 自动不可变更新(内置 Immer)
- ✅ 卓越的性能(精确更新)
- ✅ 一流的 TypeScript 支持
- ✅ 中间件生态
基本用法
import { create } from "zustand";// 创建 Store
const useBearStore = create((set, get) => ({bears: 0,fish: 10,increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),removeAllBears: () => set({ bears: 0 }),eatFishAndAddBear: async () => {const response = await fetch("/api/add-bear");const newBearCount = await response.json();const currentFish = get().fish;if (currentFish > 0) {set({ bears: newBearCount, fish: currentFish - 1 });}},
}));// 在组件中使用
function BearCounter() {const bears = useBearStore((state) => state.bears); // 选择器订阅const increasePopulation = useBearStore((state) => state.increasePopulation);return (<div><h1>{bears} around here ...</h1><button onClick={increasePopulation}>Add Bear</button></div>);
}
Jotai
Jotai 的核心概念是原子(Atom),通过组合原子来构建状态。
import { atom, useAtom } from "jotai";// 1. 创建原子
const countAtom = atom(0);
// 派生原子,用于计算衍生状态
const doubleCountAtom = atom((get) => get(countAtom) * 2);// 2. 在组件中使用
function Counter() {const [count, setCount] = useAtom(countAtom);const [doubleCount] = useAtom(doubleCountAtom);return (<div><p>{count} * 2 = {doubleCount}</p><button onClick={() => setCount((c) => c + 1)}>one up</button></div>);
}
Redux Toolkit (RTK)
RTK 是 Redux 官方推荐的、简化 Redux 使用的工具集,大幅减少了模板代码。
// 1. 使用RTK创建Slice
import { createSlice, configureStore } from "@reduxjs/toolkit";const counterSlice = createSlice({name: "counter",initialState: { value: 0 },reducers: {incremented: (state) => {state.value += 1;}, // 内部使用Immer,可直接"突变"decremented: (state) => {state.value -= 1;},},
});// 2. 创建Store
const store = configureStore({reducer: counterSlice.reducer,
});// 3. 在React组件中使用
import { useSelector, useDispatch } from "react-redux";function Counter() {const count = useSelector((state) => state.value);const dispatch = useDispatch();return (<div><span>{count}</span><button onClick={() => dispatch(counterSlice.actions.incremented())}>Increment</button></div>);
}
useReducer
useReducer 是 React 提供的一个内置 Hook,它是 useState 的替代方案,更适合管理复杂的状态逻辑。它借鉴了 Redux 的核心思想,但更加轻量化和内置化。
基本语法
const [state, dispatch] = useReducer(reducer, initialState);
基本用法
import { useReducer } from "react";// 1. 定义 reducer 函数
function counterReducer(state, action) {switch (action.type) {case "increment":return { count: state.count + 1 };case "decrement":return { count: state.count - 1 };case "reset":return { count: 0 };case "set":return { count: action.payload };default:throw new Error(`Unknown action type: ${action.type}`);}
}// 2. 在组件中使用
function Counter() {const [state, dispatch] = useReducer(counterReducer, { count: 0 });return (<div><h1>Count: {state.count}</h1><button onClick={() => dispatch({ type: "increment" })}>+1</button><button onClick={() => dispatch({ type: "decrement" })}>-1</button><button onClick={() => dispatch({ type: "reset" })}>Reset</button><button onClick={() => dispatch({ type: "set", payload: 10 })}>Set to 10</button></div>);
}
相对复杂用法
import { useReducer, useState } from "react";// 初始状态
const initialState = {todos: [],filter: "all", // all, active, completed
};// Reducer 函数
function todoReducer(state, action) {switch (action.type) {case "ADD_TODO":return {...state,todos: [...state.todos,{id: Date.now(),text: action.payload,completed: false,},],};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),};case "SET_FILTER":return {...state,filter: action.payload,};case "CLEAR_COMPLETED":return {...state,todos: state.todos.filter((todo) => !todo.completed),};default:return state;}
}function TodoApp() {const [state, dispatch] = useReducer(todoReducer, initialState);const [inputValue, setInputValue] = useState("");const addTodo = () => {if (inputValue.trim()) {dispatch({ type: "ADD_TODO", payload: inputValue });setInputValue("");}};// 根据筛选条件过滤 todosconst filteredTodos = state.todos.filter((todo) => {if (state.filter === "active") return !todo.completed;if (state.filter === "completed") return todo.completed;return true;});return (<div><h1>Todo App (useReducer)</h1><div><inputvalue={inputValue}onChange={(e) => setInputValue(e.target.value)}onKeyPress={(e) => e.key === "Enter" && addTodo()}placeholder="Add a new todo..."/><button onClick={addTodo}>Add</button></div><div><buttononClick={() => dispatch({ type: "SET_FILTER", payload: "all" })}>All</button><buttononClick={() => dispatch({ type: "SET_FILTER", payload: "active" })}>Active</button><buttononClick={() => dispatch({ type: "SET_FILTER", payload: "completed" })}>Completed</button><button onClick={() => dispatch({ type: "CLEAR_COMPLETED" })}>Clear Completed</button></div><ul>{filteredTodos.map((todo) => (<likey={todo.id}style={{textDecoration: todo.completed ? "line-through" : "none",}}><spanonClick={() =>dispatch({ type: "TOGGLE_TODO", payload: todo.id })}>{todo.text}</span><buttononClick={() =>dispatch({ type: "DELETE_TODO", payload: todo.id })}>Delete</button></li>))}</ul><div><p>Total: {state.todos.length}</p><p>Active: {state.todos.filter((t) => !t.completed).length}</p><p>Completed: {state.todos.filter((t) => t.completed).length}</p></div></div>);
}
useReducer 最佳实践
- Action 类型常量
// actions.js
export const ActionTypes = {ADD_TODO: "ADD_TODO",TOGGLE_TODO: "TOGGLE_TODO",DELETE_TODO: "DELETE_TODO",SET_FILTER: "SET_FILTER",CLEAR_COMPLETED: "CLEAR_COMPLETED",
};
- Action 创建函数
// actionCreators.js
export const addTodo = (text) => ({type: ActionTypes.ADD_TODO,payload: text,
});export const toggleTodo = (id) => ({type: ActionTypes.TOGGLE_TODO,payload: id,
});// 在组件中使用
dispatch(addTodo("Learn useReducer"));
- 结合 Context API 实现全局状态管理
import { createContext, useContext, useReducer } from "react";const TodoContext = createContext();export function TodoProvider({ children }) {const [state, dispatch] = useReducer(todoReducer, initialState);return (<TodoContext.Provider value={{ state, dispatch }}>{children}</TodoContext.Provider>);
}export const useTodo = () => {const context = useContext(TodoContext);if (!context) {throw new Error("useTodo must be used within a TodoProvider");}return context;
};// 在任何子组件中使用
function TodoList() {const { state, dispatch } = useTodo();// ...
}
