Redux 的三大原则
Redux 3 main principles
三条,每条都要说出「为什么」:
- 单一数据源(single source of truth)—— 整个应用一个 store。
为什么:状态只有一份就不会不一致, 而且整个应用的状态可以被序列化—— 这才有了「保存/恢复现场」和 SSR 脱水注水。 - state 只读—— 只能通过派发 action 改。
为什么:把「谁能改状态」收窄到一个入口, 于是所有变化都可以被记录、 可以被拦截、可以被回放。 - 用纯函数(reducer)做修改——
(state, action) => newState。
为什么:纯函数给定同样的 state 和 action 永远得到同样结果, 所以能重放、能测试、时间旅行调试才成立。
这三条是一个整体: 单一数据源让状态可序列化, 只读让变化可记录, 纯 reducer 让变化可重放 ——三者合起来才有 DevTools 的时间旅行。能把它们串起来讲比一条条背强得多。
会追问:「reducer 里能做什么不能做什么?」——不能:改传进来的 state、 发请求、读Date.now() /Math.random()、 派发别的 action。这些都放中间件或 action creator 里。
「RTK 里 state.push()违反第 2 条吗?」—— 不违反。Immer 给的是一个草稿代理(draft proxy), 你的修改被记录下来, 最终产出的是新对象,原 state 没动。
Three of them, and each one needs a “why”:
- Single source of truth — one store for the whole app.
Why: one copy of the state cannot disagree with itself, and the entire app state can be serialised — which is what makes “save and restore the session” and SSR dehydration possible. - State is read-only — you change it only by dispatching an action.
Why: it narrows “who can change state” down to one entrance, so every change can be logged, intercepted and replayed. - Changes are made by pure functions (reducers) —
(state, action) => newState.
Why: a pure function always gives the same result for the same state and action, so it can be replayed and tested, and that is what makes time-travel debugging work.
The three are one package: a single source of truth makes state serialisable, read-only makes changes loggable, and pure reducers make changes replayable — together they add up to time travel in DevTools. Tying them together like this is much stronger than reciting them one by one.
Follow-up: “What can and cannot a reducer do?” — it cannot mutate the state it was given, make requests, read Date.now() or Math.random(), or dispatch other actions. All of that belongs in middleware or an action creator.
“Does state.push() in RTK break rule 2?” — no. Immer hands you a draft proxy, records your edits, and produces a new object; the original state is untouched.