先决 Reducer 概念
正如在“Redux 基础”第 3 部分:状态、动作和 Reducers中所描述的,Redux reducer 函数:
- 应具有
(previousState, action) => newState的签名,类似于你会传递给Array.prototype.reduce(reducer, ?initialValue)的函数类型 - 应该是“纯函数”,这意味着 reducer:
- 不执行 副作用(例如调用 API 或修改非本地对象或变量)。
- 不调用 非纯函数(比如
Date.now或Math.random)。 - 不 修改 它的参数。如果 reducer 更新状态,不应该 原地修改 现有的状态对象。相反,应该生成一个包含必要更改的 新对象。对于 reducer 更新的状态中的任何子对象也应采用相同的做法。
关于不可变性、副作用和变异的说明
不推荐变异,因为它通常会破坏时间旅行调试和 React Redux 的
connect函数:
- 对于时间旅行,Redux DevTools 期望重放记录的动作能够输出状态值,但不会改变其他任何东西。副作用如变异或异步行为会导致时间旅行在步骤之间改变行为,从而破坏应用。
- 对于 React Redux,
connect会检查mapStateToProps函数返回的 props 是否变化,以确定组件是否需要更新。为了提升性能,connect采用一些依赖于状态不可变性的优化,并使用浅层引用相等检测变化。这意味着 通过直接变异修改对象和数组的更改不会被检测到,组件也不会重新渲染。其他如在 reducer 中生成唯一 ID 或时间戳等副作用也会使代码不可预测,且更难调试和测试。
由于这些规则,在继续学习组织 Redux reducer 的其他具体技术之前,务必完全理解以下核心概念:
Redux Reducer 基础
关键概念:
- 按状态和状态形状思考
- 按状态片段划分更新职责(reducer 组合)
- 高阶 reducers
- 定义 reducer 初始状态
阅读列表:
- “Redux 基础”第 3 部分:状态、动作和 Reducers
- Redux 文档:减少样板代码
- Redux 文档:实现撤销历史
- Redux 文档:
combineReducers - 高阶 Reducers 的力量
- Stack Overflow:Store 初始状态和
combineReducers - Stack Overflow:状态键名和
combineReducers
纯函数和副作用
关键概念:
- 副作用
- 纯函数
- 如何用组合函数的思路思考
阅读列表:
不可变数据管理
关键概念:
- 可变性与不可变性
- 安全地不可变更新对象和数组
- 避免会变异状态的函数和语句
阅读列表:
数据规范化
关键概念:
- 数据库结构与组织
- 将关系型/嵌套数据拆分成多个表
- 为某个项目存储单一定义
- 通过 ID 引用项目
- 使用以项目 ID 为键的对象作为查找表,使用 ID 数组来追踪排序
- 关联项目之间的关系
阅读列表: