更新 redux 存储中的嵌套数据

IT技术 javascript reactjs redux
2021-03-02 10:45:27

使用 redux 更新存储中嵌套数据数组的最佳/正确方法是什么?

我的商店看起来像这样:

{
    items:{
        1: {
            id: 1,
            key: "value",
            links: [
                {
                    id: 10001
                    data: "some more stuff"
                },
                ...
            ]
        },
        ...
    }
}

我有一对更新完整items对象的异步操作,但我有另一对要更新特定links数组的操作。

我的减速器目前看起来像这样,但我不确定这是否是正确的方法:

  switch (action.type) {
    case RESOURCE_TYPE_LINK_ADD_SUCCESS:
      // TODO: check whether the following is acceptable or should we create a new one?
      state.items[action.resourceTypeId].isSourceOf.push(action.resourceTypeLink);
      return Object.assign({}, state, {
        items: state.items,
      });
  }
2个回答

Jonny 的回答是正确的(永远不要改变给你的状态!)但我想补充一点。如果您的所有对象都有 ID,那么保持状态形状嵌套通常是个坏主意。

这:

{
  items: {
    1: {
      id: 1,
      links: [{
        id: 10001
      }]
    }
  }
}

是一种难以更新的形状。

不必这样!你可以像这样存储它:

{
  items: {
    1: {
      id: 1,
      links: [10001]
    }
  },
  links: {
    10001: {
      id: 10001
    }
  }
}

这更容易更新,因为任何实体都只有一个规范副本。如果您需要让用户“编辑链接”,则只有一个地方需要更新——而且它完全独立itemslinks.

要将您的 API 响应变成这样的形状,您可以使用normalizr一旦服务器操作中的实体被规范化,您就可以编写一个简单的 reducer 将它们合并到当前状态:

import merge from 'lodash/object/merge';

function entities(state = { items: {}, links: {} }, action) {
  if (action.response && action.response.entities) {
    return merge({}, state, action.response.entities);
  }

  return state;
}

real-world有关此类方法的演示,请参阅 Redux示例。

在 Redux 中将嵌套结构转换为更扁平的结构总是有利的吗?如果没有要非规范化的实体,只有一棵深树怎么办?类似于... { items: { 12345: { a: { b: { c: { d: { info: 'hi' }}}}}}} 我知道如果考虑性能,您可以使用 redux-ignore,那么将数据保存在这种结构中是否有任何危险(假设服务器以这种方式发送数据而我无法控制)?我不能根据需要嵌套减速器吗?
2021-04-23 10:45:27
@hisa_py 您需要单独保留一组 ID。无论real-worldshopping-cart例子Redux的回购做到这一点。
2021-04-27 10:45:27
我正在使用 normalizr,但我也需要按照它们在 API 响应中出现的相同顺序的项目。我正在考虑使用实体 ID 实现“链接列表”,但我想知道是否有更好的方法。
2021-04-30 10:45:27
Thx @Dan ... 很好很简单 ... 现在我记得我以前在例子中看到过
2021-05-15 10:45:27

React 的update()immutability helper是一种方便的方法,可以创建一个普通旧 JavaScript 对象的更新版本,而无需对其进行变异。

你给它一个要更新的源对象和一个描述需要更新的部分和需要进行的更改的路径的对象。

例如,如果一个操作具有idlink属性,并且您想将 推link送到以 为键的项目中的链接数组id

var update = require('react/lib/update')

// ...

return update(state, {
  items: {
    [action.id]: {
      links: {$push: action.link}
    }
  }
})

(示例使用 ES6 计算属性名称action.id

@HussienK 不Object.assign执行浅拷贝?
2021-04-19 10:45:27
我很好奇你为什么不选择使用Object.assign()
2021-05-05 10:45:27
请注意,update() 已被弃用,取而代之的是github.com/kolodny/immutability-helper
2021-05-07 10:45:27