更新 redux store 中的嵌套数据

Updating nested data in redux store

使用 redux 更新商店中嵌套数据数组的best/correct方法是什么?

我的店铺是这样的:

{
    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,
      });
  }

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

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

这个:

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

是一个很难更新的形状。

不一定要这样!您可以像这样存储它:

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

这更容易更新,因为任何实体只有一个规范副本。如果你需要让用户“编辑 link”,那么只有一个地方需要更新——它完全独立于 items 或任何其他引用 links 的地方。

要使您的 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;
}

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