✍️ 模拟 Dan Abramov 思路撰写
🎯 主题:Redux 三大原则并非限制,而是可控性的构建工具
🧠 关键词:单一状态树、只读状态、纯函数 reducer、前端状态建模
📜 Redux 只立了三条法则,但每一条都是“架构杀器”
Redux 的三条核心原则,很多人第一眼会觉得像“开发规范”:
- 单一数据源
- 状态只读
- 状态变更只能通过纯函数 reducer
但你错了——
这三条不是代码规范,而是前端状态世界的物理定律。 它们是为了让你在高复杂系统中保持可控、可测、可审计、可扩展。
我设计 Redux 时的第一个问题是:
“如果一个状态出了错,我怎么定位、调试、还原?”
这三条法则,就是我在“如何让状态变更变得可观测”这道题上的最终答案。
🧱 法则一:单一状态树(Single Source of Truth)
const state = {
user: {...},
posts: [...],
ui: {...}
}
为什么不是多个 store?为什么不是组件自己持有状态?
因为:
- 多 store 会导致状态分散,难以跨模块联动(如一个 user 状态改了,要同时更新多个地方);
- 多个 source of truth 会让状态无法被还原、同步、持久化、回放;
- 全局状态不可组合,会导致“状态碎片化”。
单一状态树让我们获得了:
- 🔍 快照能力(任何时刻 state 可打印、可序列化)
- ⏪ 状态回放(DevTools 回溯)
- 🪝 状态监听(React-Redux 的订阅更新)
- 🔄 服务端同步(hydrate)
“可观察性,是工程能力的前提。”
🚫 法则二:状态是只读的(Read-Only)
你可能会问:
“我直接改
store.state.user.name = 'Mark'有什么问题?”
问题不是现在看得见,而是以后你调不出来。
我们把所有状态修改路径收敛到 dispatch(action):
store.dispatch({ type: 'UPDATE_USER', payload: { name: 'Mark' } })
带来了哪些能力?
- 每次修改都有日志(如 DevTools TimeLine);
- 状态不会被“偷偷改掉”;
- 中间件可以拦截变更前后;
- 你可以记录/重放所有用户操作。
这不是“麻烦”,而是换取长期稳定性的代价。
我们牺牲了自由,但换来了:
状态修改的 唯一性、显式性、可拦截性、可验证性。
🧪 法则三:状态变更只能由纯函数 reducer 执行
function reducer(state, action) {
if (action.type === 'ADD') {
return { ...state, count: state.count + 1 }
}
return state
}
什么是纯函数?
- 不修改外部变量;
- 相同输入 ➜ 相同输出;
- 不产生副作用(如请求、日志、跳转等)。
为什么强调纯?因为我们想让你“可测”。
test('reducer works', () => {
expect(reducer({ count: 1 }, { type: 'ADD' })).toEqual({ count: 2 })
})
如果你的 reducer 里面写了 API 请求或随机数,那你就测试不了了。
“可预测性 + 可测试性 = 可维护性。”
🔬 Redux = 状态行为的数学建模系统
这三大原则合在一起,让我们可以将 Redux 看作一个状态行为的有向图系统:
State₀ --(action₁)--> State₁ --(action₂)--> State₂ ...
你拥有:
- 明确的状态变更路径;
- 明确的变更记录(action 日志);
- 明确的转移函数(reducer);
- 明确的订阅机制(connect/useSelector);
这种设计可以类比为:
- 📦 数据库的 WAL(Write Ahead Log)机制
- 🛠️ Git 的 commit 流
- 🎞️ 时间机器的时间轴系统
你拥有的是一份“前端状态的真实录像带”。
🔁 “限制”换来的是工程级别的自由
很多人会说 Redux 繁琐、冗长、写得累。
我想问:
你愿意用 setState 到处改状态,在线上踩无数坑,还是提前架设防线?
当你业务变得复杂:
- 多人协作、多人并发
- 状态之间强关联
- 调试成本高
- 跨端同步、历史还原
你会发现 Redux 是为这些场景生的。
✅ Redux 工程实践建议
| 项目场景 | 是否推荐使用 Redux |
|---|---|
| 简单组件内部状态 | ❌ 推荐 useState / useReducer |
| 中型业务系统,有多个模块状态 | ✅ 推荐使用 Redux + Redux Toolkit |
| 多端共享状态、状态需持久化、需调试 | ✅ 强烈推荐使用 Redux + DevTools |
| 组件树层级深、状态传递层级深 | ✅ 推荐 Redux 或 Context + Hooks |
🔚 总结:Redux 的三大原则,不是限制你,是保护你
Redux 的三大法则,是我们从架构维度写给工程师的一封安全保障书:
我们不是为了让你代码更优雅,而是让你在 1 年、3 年、5 年之后还能维护这套系统。
它们构建的不是“代码风格”,而是一个:
- ✅ 可追踪(Traceable)
- ✅ 可预测(Predictable)
- ✅ 可还原(Reproducible)
- ✅ 可协作(Collaborative)
的状态模型。
⏭️ 下一篇预告
你听我讲了这么多哲学,是时候打开 Redux 的大脑了:
下一篇,我们进入 Redux 的核心函数:
createStore()。 我将逐行带你解析 Redux 是如何实现状态容器、监听机制、以及 dispatch 流程的。