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

IT技术 reactjs redux immutable.js
2021-04-08 23:25:00

鉴于我最初的 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 有一些技巧可以减少react渲染时间,它满足所有项目要求。此外,在项目中使用新库而无需进行重大更改还为时过早。

2个回答

首先,惯用的 Redux 鼓励您“标准化”您的状态并尽可能地将其扁平化。使用以项目 ID 为键的对象允许直接查找项目,使用 ID 数组表示排序,并且在一个项目需要引用另一个项目的任何地方,它只存储另一个项目的 ID 而不是实际数据。这允许您对嵌套对象进行更简单的查找和更新。请参阅有关嵌套数据的 Redux FAQ 问题

此外,您目前似乎在 Redux 状态中直接存储了许多函数。 从技术上讲这是可行的,但它绝对不是惯用的,并且会破坏时间旅行调试等功能,因此非常不鼓励这样做。Redux FAQ 提供了更多关于为什么在你的 Redux 状态中存储不可序列化的值是一个坏主意的信息

编辑:

作为后续,我最近在 Redux 文档中添加了一个新部分,主题是“结构化减速器”特别是,本节包括关于“规范化状态形状”“更新规范化数据”以及“不可变更新模式”的章节

例子会很好
2021-05-27 23:25:00
所有链接都已损坏。
2021-06-06 23:25:00
这似乎是最“正确”的答案,并且在 state 中存储文字函数是一个快速修复,在发布之前将更改为更传统的方法。
2021-06-10 23:25:00
当然。您可能会看到的一种相关方法是在您的状态中存储某种过滤器名称或标识符,然后将其用作在组件或选择器中查找实际过滤器功能的键,类似于建议用于管理对话框组件的方法在stackoverflow.com/questions/35623656/...
2021-06-14 23:25:00
我们最近确实更新了 docs 构建工具,它更改了 URL。它应该重定向旧的 URL,但这似乎不起作用。我会更新链接。
2021-06-17 23:25:00

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

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

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

通过分解我的减速器,我仍然会得到复杂的对象,它们只是稍微减少了嵌套。没有遗漏任何重要内容,只是一个有用的链接,以防其他人在谷歌上搜索此问题。
2021-05-23 23:25:00
@StevenBayer 我错过了什么重要的事情吗?
2021-05-26 23:25:00
我不知道我将如何实现一个子减速器上state.roomLists或更是如此state.roomLists[n].listItems[n]子减速器的太阳功能也不会加起来成为一个深度克隆吗?
2021-06-08 23:25:00
@StevenBayer 您的状态树将保持不变。但是在每个减速器中,您将处理更简单的数据结构。对不起,我在帖子中没有说清楚。此外,您并不总是需要combineReducer. Reducers 只是将stateaction作为参数的函数。您可以在一个reducer 函数中调用另一个reducer 函数来减少每个reducer 的职责。
2021-06-16 23:25:00