简体   繁体   English

在redux存储中更新嵌套数据

[英]Updating nested data in redux store

What's the best/correct way to update a nested array of data in a store using redux? 使用redux更新商店中嵌套数据的最佳/正确方法是什么?

My store looks like this: 我的商店看起来像这样:

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

I have a pair of asynchronous actions that updates the complete items object but I have another pair of actions that I want to update a specific links array. 我有一对异步操作来更新完整的items对象,但我有另一对我想要更新特定links数组的操作。

My reducer currently looks like this but I'm not sure if this is the correct approach: 我的减速机目前看起来像这样,但我不确定这是否是正确的方法:

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

Jonny's answer is correct (never mutate the state given to you!) but I wanted to add another point to it. Jonny的回答是正确的(永远不会改变给你的状态!)但我想补充一点。 If all your objects have IDs, it's generally a bad idea to keep the state shape nested. 如果所有对象都有ID,那么保持状态形状嵌套通常是个坏主意。

This: 这个:

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

is a shape that is hard to update. 是一种难以更新的形状。

It doesn't have to be this way! 它不一定是这样! You can instead store it like this: 你可以这样存储它:

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

This is much easier for update because there is just one canonical copy of any entity. 这更容易更新,因为只有一个任何实体的规范副本。 If you need to let user “edit a link”, there is just one place where it needs to be updated—and it's completely independent of items or anything other referring to links . 如果您需要让用户“编辑链接”,则只需要更新一个位置 - 它完全独立于items或其他任何指向links

To get your API responses into such a shape, you can use normalizr . 要将API响应变为这样的形状,可以使用normalizr Once your entities inside the server actions are normalized, you can write a simple reducer that merges them into the current state: 一旦您的服务器操作中的实体被规范化,您就可以编写一个简单的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;
}

Please see Redux real-world example for a demo of such approach. 有关此类方法的演示,请参阅Redux real-world示例。

React's update() immutability helper is a convenient way to create an updated version of a plain old JavaScript object without mutating it. React的update() immutability helper是一种创建普通旧JavaScript对象的更新版本而不会改变它的便捷方式。

You give it the source object to be updated and an object describing paths to the pieces which need to be updated and changes that need to be made. 您可以为其提供要更新的源对象,以及描述需要更新的部分的路径的对象以及需要进行的更改。

eg, if an action had id and link properties and you wanted to push the link to an array of links in an item keyed with the id : 例如,如果某个操作具有idlink属性,并且您希望将link推送到以id键入的项目中的链接数组:

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

// ...

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

(Example uses an ES6 computed property name for action.id ) (示例使用action.id的ES6计算属性名称)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM