如何在JavaScript中实现状态管理_从单向数据流到Redux模式详解【教程】

15次阅读

90%的中小型react应用用usereducer+useContext足够;Redux Toolkit才值得在需时间旅行、服务端同步、复杂中间件或跨组件高频共享状态时评估;派生状态不应进store,而该用useMemo或createSelector计算。

如何在JavaScript中实现状态管理_从单向数据流到Redux模式详解【教程】

javaScript 中不需要“从单向数据流讲到 Redux 模式”来实现状态管理——真正需要的,是根据场景选对工具,避免过早抽象。

什么时候该自己写 useState + useReducer,而不是引入 Redux?

90% 的中小型 React 应用,useReducer 配合 useContext 就够用了。Redux 的核心价值不在“状态可预测”,而在于:需要时间旅行调试、服务端状态同步、大量中间件(如 redux-thunkredux-saga)、跨多个不相关组件共享且频繁更新的状态。

  • 表单联动、模态框开关、主题切换 → 用 useStateuseReducer
  • 购物车 + 用户登录态 + 实时通知三者互相影响 → 可考虑 useReducer + 自定义 Hook 封装
  • 需要回放用户操作、离线优先、与后端状态强一致 → 才值得评估 Redux Toolkit(不是原生 Redux)

useReducer 的常见误用:把所有 state 都塞进一个 reducer

这不是单向数据流的问题,是职责混淆。一个 reducer 应该只负责一类逻辑闭环的状态变更,比如 cartReducer 管购物车,authReducer 管登录态,而不是全塞进 appReducer

错误示例:

立即学习Java免费学习笔记(深入)”;

const appReducer = (state, action) => {   switch (action.type) {     case 'ADD_TO_CART':       return { ...state, cart: [...state.cart, action.item] };     case 'LOGIN_SUCCESS':       return { ...state, user: action.user, isLoggedIn: true };     case 'NOTIFY':       return { ...state, notifications: [...state.notifications, action.msg] };     default:       return state;   } };

问题:任意 action 都可能意外修改其他字段;无法单独测试;reducer 越来越大。

推荐做法:拆分 + 组合

const cartReducer = (state, action) => { /* ... */ }; const authReducer = (state, action) => { /* ... */ }; 

const rootReducer = (state, action) => ({ cart: cartReducer(state.cart, action), auth: authReducer(state.auth, action), });

Redux Toolkit 的 createSlice 不是语法糖,它解决了原生 Redux 的三个硬伤

很多人以为 createSlice 只是自动写 action.type 字符串,其实它关键在:immer 支持可变写法、自动合并 reducersextraReducers、内置 createAsyncThunk 处理副作用。

  • 不用再手写 switchreturn {...state} —— 直接 state.items.push(item)
  • 异步请求不再需要三层 action(PENDING/FULFILLED/REJECTED)手动 dispatch
  • configureStore 默认开启 serializableCheckimmutableCheck,提前暴露不可序列化值(如函数、date

典型漏掉的配置:

import { configureStore } from '@reduxjs/toolkit'; import { setupListeners } from '@reduxjs/toolkit/query'; 

const store = configureStore({ reducer: { / ... / }, middleware: (getDefault) => getDefault().concat(yourCustomMiddleware), // 忘加这行,RTK Query 不生效 });

setupListeners(store.dispatch); // 忘加这行,refetch 等行为不触发

状态管理最容易被忽略的复杂点:派生状态不该进 store

比如「购物车总价」、「已读消息数」、「筛选后的商品列表」——这些是计算结果,不是源状态。放进 Redux store 会导致:重复计算、缓存失效、与原始数据不同步。

正确方式:

  • React 中用 useMemocreateSelector(Reselect)缓存派生值
  • Redux Toolkit 中用 createEntityAdapter + getSelectors 自动处理排序/过滤
  • 永远只在 store 里存 cartItems: [{id, qty}],不要存 totalPrice: 129.99

一旦发现某个字段总要和另一个字段一起更新,或者每次都要靠 useEffect 同步它,那它大概率不该是独立 state。

text=ZqhQzanResources