在redux存储中更新嵌套数据

Cla*_*kie 47 javascript reactjs redux

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

我的商店看起来像这样:

{
    items:{
        1: {
            id: 1,
            key: "value",
            links: [
                {
                    id: 10001
                    data: "some more stuff"
                },
                ...
            ]
        },
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一对异步操作来更新整个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,
      });
  }
Run Code Online (Sandbox Code Playgroud)

Dan*_*mov 58

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

这个:

{
  items: {
    1: {
      id: 1,
      links: [{
        id: 10001
      }]
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

是一种难以更新的形状.

它不一定是这样!你可以这样存储它:

{
  items: {
    1: {
      id: 1,
      links: [10001]
    }
  },
  links: {
    10001: {
      id: 10001
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这更容易更新,因为只有一个任何实体的规范副本.如果您需要让用户"编辑链接",那么只需要更新一个位置 - 它完全独立于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;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 在Redux中将嵌套结构转换为更平坦的结构总是有利的吗?如果没有实体去反规范化,只是一棵深树怎么办?类似...... {item:{12345:{a:{b:{c:{d:{info:'hi'}}}}}}}我知道如果性能有任何考虑,你可以使用redux-ignore,那么在这个结构中保存数据是否有任何危险(比如服务器是否以这种方式发送并且我无法控制)?我不能只根据需要筑巢减速器吗? (10认同)

Jon*_*nan 50

React的update()immutability helper是一种创建普通旧JavaScript对象的更新版本而不会改变它的便捷方式.

您可以为其提供要更新的源对象,以及描述需要更新的部分的路径的对象以及需要进行的更改.

例如,如果一个动作有idlink属性,并且你想要将link一个项目中的一个链接推送到一个键入的项目id:

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

// ...

return update(state, {
  items: {
    [action.id]: {
      links: {$push: action.link}
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

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

  • 请注意,不推荐使用update()以支持https://github.com/kolodny/immutability-helper (6认同)