
Redux 作为前端经典状态管理库,核心解决 "组件间状态共享" 与 "状态变更可追溯" 问题,适配大型 React 项目。这篇文章我通过结合手写核心逻辑 与现代工具 RTK,拆解 Redux 原理,明晰 "底层原理" 与 "高效开发" 的协同路径
一、Redux 核心三要素:Action、Reducer、Store
Redux 遵循单向数据流 ,状态变更需经 Action → Reducer → Store
流程,确保可预测性。
1. Action:操作描述的 "消息载体"
Action 是触发状态变更的 "入口",本质是平面对象 (需 isPlainObject
验证),核心作用是描述 "发生了什么操作",可通过 payload
携带数据。
核心特性(结合手写代码)
-
必须含
type
属性 :标识操作类型(如INCREMENT
),类型无强制约束(字符串、Symbol 均可),大型项目建议单独维护(如actionTypes.js
)避免硬编码。示例:
js// 基础 Action 结构 const incrementAction = { type: "INCREMENT", payload: 1 };
-
Action 创建函数(Action Creator) :用纯函数 简化 Action 生成,函数无副作用(不修改参数、无异步、不影响外部环境)。
示例:
js// 生成"增加计数"的 Action const increment = (step) => ({ type: "INCREMENT", payload: step });
-
bindActionCreators
:自动分发 Action手动创建 Action 需调用
store.dispatch(action)
触发变更,bindActionCreators
可增强 Action Creator,使其创建后自动分发 ,简化代码。核心实现(手写逻辑):
jsfunction getAutodisPatchActionCreator(actionCreator, dispatch) { return (...args) => { const action = actionCreator(...args); dispatch(action); }; } export default function bindActionCreators(actionCreators, dispatch) { if (typeof actionCreators === 'function') { return getAutodisPatchActionCreator(actionCreators, dispatch); } const result = {}; for (const key in actionCreators) { const creator = actionCreators[key]; if (typeof creator === 'function') { result[key] = getAutodisPatchActionCreator(creator, dispatch); } } return result; }
2. Reducer:状态计算的 "纯函数"
Reducer 是 Redux 的 "状态计算核心",接收当前 state
和 Action,返回新状态(不可修改原状态),决定 "如何根据操作变更状态"。
核心特性(结合手写代码)
-
必须是纯函数:保障 Redux 可预测性,要求:
- 不修改入参
state
和action
; - 无异步操作(如定时器、接口请求);
- 不影响外部环境(如修改全局变量、操作 DOM)。
优势:纯函数便于测试、可还原状态,且能优化 React 组件渲染(避免不必要重绘)。
- 不修改入参
-
初始化状态的技巧
创建 Store 时,Redux 自动分发初始化 Action (类型为
@@redux/INIT + 随机字符串
,由ActionTypes.INIT()
生成),此时 Reducer 接收state = undefined
,可通过参数默认值初始化状态:js// 计数状态管理示例 function countReducer(state = 0, action) { switch (action.type) { case "INCREMENT": return state + action.payload; case "DECREMENT": return state - action.payload; default: return state; } }
-
combineReducers
:拆分复杂 Reducer大型项目状态结构复杂(如 "用户信息""购物车"),需按 "状态模块" 拆分 Reducer,再用
combineReducers
合并为根 Reducer 。核心实现(手写逻辑):
jsexport default function combineReducers(reducers) { validateReducers(reducers); return function (state = {}, action) { const newState = {}; for (const key in reducers) { if (reducers.hasOwnProperty(key)) { const subReducer = reducers[key]; newState[key] = subReducer(state[key], action); } } return newState; }; }
示例(合并 "用户" 与 "计数" 模块):
jsconst rootReducer = combineReducers({ user: userReducer, count: countReducer }); // Store 状态结构:{ user: {...}, count: 0 }
3. Store:状态的 "统一容器"
Store 是 Redux 中 "唯一的状态容器",通过 createStore(reducer)
创建,封装状态存储、分发 Action、监听状态变化的核心能力。
核心方法(手写实现)
-
getState()
:获取当前状态直接返回 Store 内部保存的
currentState
,是组件获取状态的唯一途径:jsfunction getState() { return currentState; }
-
dispatch(action)
:触发状态变更唯一能修改状态的方法,流程:
① 验证 Action(必须是平面对象,且含
type
);② 调用 Reducer,传入当前状态和 Action,计算新状态;
③ 执行所有监听器(
listeners
),通知状态变更。核心代码:
jsfunction dispatch(action) { if (!isPlainObject(action)) { throw new TypeError("action must be a plain object"); } if (action.type === undefined) { throw new TypeError("action must has a property of type"); } currentState = currentReducer(currentState, action); for (const listener of listeners) { listener(); } }
-
subscribe(listener)
:监听状态变化注册 "状态变更监听器"(无参函数),
dispatch
触发后执行所有监听器;返回 "取消监听" 函数,避免内存泄漏。核心代码:
jsfunction subscribe(listener) { listeners.push(listener); let isRemoved = false; return function () { if (isRemoved) return; const index = listeners.indexOf(listener); listeners.splice(index, 1); isRemoved = true; }; }
-
Store 初始化
创建 Store 时,自动分发初始化 Action (
ActionTypes.INIT()
),触发 Reducer 执行,通过参数默认值完成状态初始化(无需手动传默认状态)。
二、Redux 工具函数与中间件
1. 工具函数:保障核心逻辑合法性
-
isPlainObject(obj)
:验证平面对象(__proto__
指向Object.prototype
),避免非标准对象(如数组、类实例)导致逻辑异常。jsexport default function isPlainObject(obj) { if (typeof obj !== "object") return false; return Object.getPrototypeOf(obj) === Object.prototype; }
-
ActionTypes
:生成随机初始化 Action 类型(如@@redux/INIT + 随机字符串
),避免与业务 Action 冲突。jsfunction getRandom(length) { return Math.random().toString(36).slice(2, length + 2).split("").join("."); } export default { INIT() { return `@@redux/INIT${getRandom(6)}`; }, UNKNOWN() { return `@@redux/PROBE_UNKNOWN_ACTION${getRandom(6)}`; } };
2. 中间件:增强 dispatch
能力
Redux 核心仅支持同步 Action ,处理异步操作(如接口请求)需通过中间件 扩展 dispatch
功能。
中间件本质是 "函数链",在 dispatch
触发 Action 后、Reducer 执行前,插入自定义逻辑(如异步请求、日志、错误捕获)。常见中间件:
-
redux-thunk
:支持函数式 Action(Action 可返回函数,内部执行异步操作); -
redux-saga
:用 Generator 管理复杂异步流程(如接口重试、竞态处理)。
核心原理 :中间件包装 store.dispatch
,支持非标准 Action(如函数、Promise),待异步完成后,分发真正的 "同步 Action" 触发状态变更。
三、从手写 Redux 到 RTK:现代开发的演进
现代开发中,Redux 官方推出 Redux Toolkit(RTK) ,封装 createSlice
(合并 Action 与 Reducer)、configureStore
(简化 Store 创建,内置中间件)等工具,大幅减少重复代码(无需手动写 combineReducers
、bindActionCreators
),已成为 Redux 开发的推荐方案。
手写核心 vs RTK:定位与价值
- 手写核心 :并非替代 RTK,而是为了深入理解 Redux 底层逻辑。掌握核心原理后,能更灵活应对 RTK 封装的 "黑盒场景"(如自定义中间件、调试复杂状态流)。
- RTK :基于 Redux 核心逻辑的高效工具 ,让开发更简洁(如
createSlice
自动生成 Action 与 Reducer),适合快速迭代的项目。
RTK 关键工具示例
-
createSlice
:合并 Action 类型、Reducer、Action Creator,自动生成 Action(如increment
)。jsimport { createSlice } from '@reduxjs/toolkit'; const counterSlice = createSlice({ name: 'counter', initialState: 0, reducers: { increment: (state, action) => state + action.payload, decrement: (state, action) => state - action.payload, }, }); // 自动生成 Action Creator:counterSlice.actions.increment
-
configureStore
:简化 Store 创建,内置redux-thunk
、redux-devtools
等中间件。jsimport { configureStore } from '@reduxjs/toolkit'; const store = configureStore({ reducer: rootReducer, });
四、Redux 工作流程与核心价值
1. 完整流程(手写与 RTK 通用)
- 组件调用 Action Creator(或 RTK 的
slice.actions
)触发 Action; dispatch
传递 Action 至 Reducer;- Reducer 计算新状态,更新 Store;
- 监听器(如 React 组件的重新渲染逻辑)触发组件更新,读取新状态(
store.getState()
)。
2. 核心价值
Redux 通过分离 Action、Reducer、Store ,让状态变更可追溯、可测试,尤其适配大型项目的复杂状态管理。
- 手写核心:是理解 Redux 设计思想的 "最佳路径",掌握后能精准定位状态问题;
- RTK:是高效开发的 "助推器",让 Redux 从 "繁琐配置" 转向 "简洁实践"。
五、总结
Redux 的核心价值在于规范状态管理流程,手写实现揭示其 "简洁而严谨" 的逻辑(纯函数、单向数据流);RTK 则是站在 Redux 肩膀上的 "现代工具",让开发更高效。
对于我们开发者而言:
-
新手可先通过手写核心理解原理,再迁移到 RTK 简化开发;
-
进阶者需兼顾 "底层逻辑" 与 "工具应用",让 Redux 真正服务于项目稳定性与可维护性。
二者相辅相成,共同构建前端状态管理的 "清晰脉络"。
如果您觉得这篇文章对您有帮助,欢迎点赞和收藏,大家的支持是我继续创作优质内容的动力🌹🌹🌹也希望您能在😉😉😉我的主页 😉😉😉找到更多对您有帮助的内容。
- 致敬每一位赶路人