React-Redux复杂(深层)状态对象

时间:2016-06-22 23:58:20

标签: reactjs redux immutable.js

鉴于我的初始redux状态是:

const state = {
  currentView: 'ROOMS_VIEW',
  navbarLinks: List([
    {name: 'Rooms', key: 'ROOMS_VIEW'},
    {name: 'Dev', key: ''}
  ]),
  roomListsSelected: {group: 0, item: 0},
  roomLists: [
    {
      name: "Filters",
      expanded: true,
      listItems: [
        { icon: 'images/icon-warning.svg', name: 'Alerts', filter: room => room.hasAlert },
        { icon: 'images/icon-playlist.svg', name: 'In Progress', filter: room => room.progress > 20 },
        { icon: 'images/icon-playlist.svg', name: 'Almost Done', filter: room => room.progress > 90 },
        { icon: 'images/icon-playlist.svg', name: 'Complete', filter: room => room.status === 'complete' },
        { icon: 'images/icon-playlist.svg', name: 'Recently Completed', filter: room => false },
        { icon: 'images/icon-playlist.svg', name: 'All Rooms', filter: room => true }
      ]
    }
  ],
  rooms: List(generateRooms())
}

我需要制作一个执行此操作的减速器:

state.roomList[n].expanded = !state.roomList[n].expanded

我是使用Redux工作流程的新手,解决此问题的最佳方法是使roomList成为一个immutable.js对象,或编写一些代码来深入克隆我的状态对象。

state.roomList还将从未来的功能中推送到新的数据。

Summery / Question:在状态深处进行类似更改时,在reducer中返回新状态对象的最佳方法是什么,还是应该更改Redux状态对象的结构?

我做了什么最终,Immutable似乎要走了。有一些不可变的技巧可以减少反应渲染时间,并且满足所有项目要求。此外,在项目中尽早使用新库而不进行重大更改。

2 个答案:

答案 0 :(得分:47)

首先,惯用的Redux鼓励您“规范化”您的状态并尽可能地平整它。使用按项目ID键入的对象允许直接查找项目,使用ID数组表示排序,以及一个项目需要引用另一个项目的任何地方,它只存储其他项目的ID而不是实际数据。这允许您进行更简单的查找和嵌套对象的更新。请参阅the Redux FAQ question on nested data

此外,您似乎正在直接在Redux状态下存储许多功能。 技术上有效,但它绝对不是惯用的,会破坏时间旅行调试等功能,所以非常气馁。 Redux常见问题解答提供了有关why storing non-serializable values in your Redux state is a bad idea的更多信息。

编辑:

作为后续行动,我最近在Redux文档中添加了一个关于"Structuring Reducers"主题的新部分。特别是,此部分包含有关"Normalizing State Shape""Updating Normalized Data"以及"Immutable Update Patterns"的章节。

答案 1 :(得分:6)

减速剂成分: 将减速器分解成较小的部件,以便减速器足够小以处理简单的数据结构。例如。在您的情况下,您可能会:roomListReducer listItemsReducer listItemReducer。然后在每个减速器上,它将使您更容易阅读您正在处理的状态的哪个部分。它有很大的帮助,因为你的每个减速器都在处理你不必担心的小块数据,比如“我应该深刻复制还是浅层复制”。

<强>不可变 我个人不会使用immutable.js,因为我更喜欢处理普通对象。并且有太多的代码要改变以采用新的API。但这个想法是,确保你的状态变化总是通过纯函数来完成。因此,您可以简单地编写自己的帮助函数来执行您想要的操作,只需确保在处理复杂对象时对它们进行彻底测试。

或者简单地说,你总是可以在每个reducer中深度复制你的状态,然后在副本中变异然后返回副本。但这显然不是最好的方式。