【问题标题】:React-Redux complex (deep) state objectsReact-Redux 复杂(深层)状态对象
【发布时间】:2016-10-25 02:36:04
【问题描述】:

鉴于我最初的 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 还将有新数据从未来的功能推送到它。

总结/问题:在状态深处进行这样的更改时,在减速器中返回新状态对象的最佳方法是什么,或者我应该更改 Redux 状态对象的结构?

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

【问题讨论】:

  • 您有问题吗?
  • 在状态深处进行这样的更改时,在 reducer 中返回新状态对象的最佳方法是什么,或者我应该更改 Redux 状态对象的结构?

标签: reactjs redux immutable.js


【解决方案1】:

首先,惯用的 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" 的章节。

【讨论】:

  • 这似乎是最“正确”的答案,并且在状态中存储文字函数是一种快速修复,将在发布之前更改为更传统的方法。
  • 当然。您可能会看到的一种相关方法是在您的状态中存储某种过滤器名称或标识符,然后将其用作在组件或选择器中查找实际过滤器功能的键,类似于建议用于管理对话框组件的方法在stackoverflow.com/questions/35623656/…
  • 例子会很好
  • 所有链接都断开了。
  • 我们最近确实更新了文档构建工具,它改变了 URL。它应该重定向旧的 URL,但这似乎无法正常工作。我会更新链接。
【解决方案2】:

减速机成分: 将reducer 分解成更小的部分,这样reducer 就足够小来处理简单的数据结构。例如。在您的情况下,您可能有:roomListReducerlistItemsReducerlistItemReducer。然后在每个 reducer 上,它会让你更容易阅读你正在处理的状态的哪一部分。这很有帮助,因为您的每个 reducer 都在处理一小部分数据,您不必担心诸如“我应该深拷贝还是浅拷贝”之类的事情。

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

或者简单地说,您可以随时在每个 reducer 中深度复制您的状态,并在副本中进行变异,然后返回副本。但这显然不是最好的方法。

【讨论】:

  • @StevenBayer 我错过了什么重要的事情吗?
  • 通过分解我的减速器,我仍然会得到复杂的对象,它们只是稍微少了嵌套。没有什么重要的遗漏,只是一个有用的链接,以防其他人用谷歌搜索这个问题。
  • @StevenBayer 你的状态树将保持不变。但是在每个 reducer 中,您将处理更简单的数据结构。对不起,我在帖子中没有说清楚。此外,您并不总是需要combineReducer。减速器只是将stateaction 作为参数的函数。你可以在一个reducer函数中调用另一个reducer函数来减少每个reducer的职责。
  • 我不确定如何在state.roomLists 上实现子减速器,或者在state.roomLists[n].listItems[n] 上实现更多。也不会 sub-reducers 的 sun 功能加起来是一个深度克隆吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-26
  • 1970-01-01
  • 1970-01-01
  • 2017-08-27
  • 1970-01-01
  • 2019-04-28
相关资源
最近更新 更多