如何更新 reducer 中嵌套对象的值?

How to update a value of a nested object in a reducer?

我已经建立了我的状态

const list = {
  categories: {
   Professional: {
    active: false,
    names: [
      {
        id: 1,
        name: "Golf",
        active: false
      },
      {
        id: 2,
        name: "Ultimate Frisbee",
        active: false
      }
  ] 
}}

在我的操作中,我添加了一个 ID 选项,因此我想在用户单击该选项时更改活动状态

我正在使用 Immutable JS,但并未与之结婚。我想知道如何定位对象的 id 并在 reducer 中更新其活动状态?我也乐于接受有关如何更好地改善我的状态的反馈

Structuring Reducers covers this. In particular, see the section on Immutable Update Patterns 上的 Redux 文档部分。给出的示例适用于普通 JS 对象和数组,但同样的方法适用 - map() 覆盖列表,return 现有项目用于您 的所有内容想要更新并且 return 为您 想要更新的版本的新版本。

根据文档,另请注意,如果您的数据存储在规范化结构中,则更新特定项目会更容易,因为您可以直接按 ID 查找它。 "Structuring Reducers" 部分也涵盖规范化。

这是很常见的事情,实际上,也很令人生畏。据我所知,在纯 JS 中没有真正好的和被广泛采用的解决方案。最初,使用 Object.assign 方法:

return Object.assign({}, state, {
  categories: Object.assign({}, state.categories, {
    Professional: Object.assign({}, state.Professional, {
      active: true
    })
  })
});

这太简单太麻烦了,我承认,但我不得不说,我们已经用这种方法构建了几个大型应用程序,除了字符数之外,它还不错。现在,最流行的方法是使用 Object spread:

return {
  ...state,
  categories: {
    ...state.categories,
    Professional: {
      ...state.categories.Professional,
      active: true
    }
  }
}

第二种方法更简洁,所以如果你使用纯 JS,那么它似乎是一个不错的选择。 在 Immutable.js 中,我不得不承认它更容易,您只需执行下一个

return state.updateIn(['categories', 'Professional'], x => x.set('active', true));

但它有其自身的缺点和注意事项,因此在实施之前最好认真考虑一下。

你最后一个关于改善状态的问题——通常最好不要有这么深的嵌套(把你的关注点分开,很多时候字段不依赖彼此——比如 active 状态可以分开到另一个对象),但由于不了解您的领域,所以很难说。此外,normalize 您的数据被认为是正常的事情。