管理归一化数据
如 归一化数据 章节所提及的,我们经常使用 Normaizr 库将嵌套式数据转化为适合集成到 store 中的归一化数据。但这并不解决针对归一化的数据进一步更新后在应用的其他地方使用的问题。根据喜好有很多种方法可供使用。下面展示一个向文章添加评论处理 mutations 的示例。
标准方法
简单合并
一种方法是将 action 的内容合并到现有的 state。在这种情况下,我们可以使用深度递归 merge,而不是浅拷贝,来允许包含部分评论的 action 更新store 中的评论。Lodash 的
merge
方法可以帮我们处理这个:
这样做会让 reducer 保持最小的工作量,但需要 action creator 在 action dispatch 之前做大量的工作来将数据转化成正确的形态。在删除数据项时这种方式也是不适合的。
Slice Reducer 组合
如果我们有一个由 slice reducer 组成的嵌套树,每个 slice reducer 都需要知道如何适当地响应这个 action。因为我们需要让 action 囊括所有相关的数据。譬如更新相应的 Post 对象需要生成一个 comment 的 id,然后使用 id 作为 key 创建一个新的 comment 对象,并且让这个 comment 的 id 包含在所有的 comment id 列表中。下面是一个如何组合这样数据的例子:
译者注:结合上章节中归一化之后的 state 阅读
这个例子之所以有点长,是因为它展示了不同 slice reducer 和 case reducer 是如何配合在一起使用的。注意这里对 “委托” 的理解。postById slice reducer 将工作委托给 addComment,addComment 将新的评论 id 插入到相应的 Post 项中。同时 commentsById 和 allComments 的 slice reducer 都有自己的 case reducer,他们会适当地更新 Comment 查找表和所有Comment id 的列表。
其他方法
基于任务的更新
slice reducer 仅仅是个函数,因此有无数种方法来拆分这个逻辑。使用 slice reducer 是最常见,但也可以在更面向任务的结构中组织行为。由于通常会涉及到更多嵌套的更新,因此常常会使用 dot-prop-immutable 、 object-path-immutable 等库实现不可变更新。下面是一个相似的例子:
这种方法让
ADD_COMMENT
这个 case 要干哪些事更加清楚,但需要更新嵌套逻辑和对特定状态树的了解。最后这取决于你如何组织 reducer 逻辑,或许你根本不需要这样做。
Redux-ORM
Redux-ORM 库提供了一个非常有用的抽象层,用于管理 Redux store 中存储的归一化数据。它允许你声明 Model 类并且定义他们之间的关系。然后它可以为你的数据类型生成新“表”,充当用于查找数据的特殊选择器工具,并且对数据执行不可变更新。
有几种方法可以用 Redux-ORM 执行数据更新。首选,Redux-ORM 文档建议在每个 Model 子类上定义 reducer 函数,然后将自动生成的组合 reducer 函数放到 store 中:
Redux-ORM 库维护要应用的内部更新队列。这些更新是不可变更新,这个库简化了这个更新过程。
使用 Redux-ORM 的另一个变化是用一个单一的 case reducer 作为抽象层。
通过使用 session interface,你现在可以使用关系访问器直接访问引用模型: