订阅机制和状态更新
Redux Store 在每次 dispatch 导致 state 更新后,同步通知所有 subscribe 注册的 listener。React 组件通过 react-redux 间接订阅,不在 core 里实现。
1. 端到端更新链
mermaid
sequenceDiagram
participant UI
participant D as dispatch
participant R as reducer
participant L as listeners
participant RR as react-redux
UI->>D: action
D->>R: 计算 nextState
R->>L: 通知
L->>RR: 触发 connect/hooks 检查
RR->>UI: 必要时重渲染2. subscribe 语义
| 点 | 说明 |
|---|---|
| 无参数 | listener 需自己 store.getState() |
| 同步 | 在 dispatch 栈内执行完毕 |
| 取消 | unsubscribe() |
| 不重入 | dispatch 中 subscribe/unsubscribe 行为受 isDispatching 约束 |
设计原因见 08 §二。
3. 与 React 的连接(概念)
react-redux(非 redux 包):
useSelector(selector):订阅 store,selector 返回值用===比较(默认)。connect(mapState):同理 + 合并 props。- 批量:React 18 自动批处理多次 setState;多次 dispatch 在事件处理中也可合并渲染。
外部 store 对比:Zustand 用 useSyncExternalStore;Redux 用 react-redux 封装的历史模式 + 相等性检查。
4. 性能要点
| 策略 | 说明 |
|---|---|
| 细 selector | 只选需要 slice,避免 state => state |
| 记忆 selector | reselect / RTK createSelector |
| 稳定引用 | reducer 未变 slice 返回原引用 |
| 避免在 listener 里重 dispatch | 易循环 |
5. 高级用法
- store.subscribe` + 手动渲染:非 React 环境。
- middleware 里订阅:少见,注意顺序。
- replaceReducer:热更新保留 state 形状。
6. 常见问题
| 现象 | 排查 |
|---|---|
| 组件不更新 | selector 引用未变;未连 Provider |
| 更新两次 | StrictMode + 错误 effect;或两个 store |
| 拿到旧 state | listener 闭包;应用 getState() 现读 |
7. 总结
订阅层极薄:notify all;性能在 selector 与 reducer 引用稳定性。现代项目优先 RTK + useSelector,但底层仍是本文模型。