使用Javascript / Lodash替换Redux Store中对象数组中的对象

时间:2016-08-18 05:01:56

标签: object reactjs redux store lodash

我在reducer中有一个对象数组,如下所示:

[
  {id:1, name:Mark, email:mark@email.com}, 
  {id:2, name:Paul, email:paul@gmail.com}, 
  {id:3,name:sally, email:sally@email.com} 
]

下面是我的减速机。到目前为止,我可以通过以下方法向currentPeople减速器添加一个新对象:

const INITIAL_STATE = { currentPeople:[]};

export default function(state = INITIAL_STATE, action) {
  switch (action.type) {
    case ADD_PERSON:
      return {...state, currentPeople: [ ...state.currentPeople, action.payload]}; 
  }
  return state;
}

但这里是我被困的地方。我可以使用lodash通过减速机更新一个人吗? 如果我发送了一个如下所示的动作有效负载:

  {id:1, name:Eric, email:Eric@email.com}

我是否可以使用新字段替换id为1的对象?

3 个答案:

答案 0 :(得分:4)

是的,你绝对可以像你想的那样更新数组中的对象。如果您不想,也不需要更改数据结构。您可以在减速器中添加这样的案例:

case UPDATE_PERSON: 
    return {
        ...state, 
        currentPeople: state.currentPeople.map(person => {
            if (person.id === action.payload.id) {
               return action.payload;
            }

            return person;
        }),
    };

这也可以缩短,使用隐式返回和三元:

case UPDATE_PERSON: 
    return {
        ...state, 
        currentPeople: state.currentPeople.map(person => (person.id === action.payload.id) ? action.payload : person),
    };

Mihir关于使用normalizr将数据映射到对象的想法当然是一种可能性,从技术上讲,使用引用更新用户而不是执行循环(初始映射完成后)会更快。但是如果你想保留你的数据结构,这种方法就可以了。

此外,像这样的映射只是更新对象的众多方法之一,并且需要对Array.prototype.map()的浏览器支持。您可以使用lodash indexOf()来查找所需用户的索引(这很好,因为它在成功时会中断循环,而不是像.map那样继续循环),一旦有索引就可以覆盖对象直接使用它的索引。确保你不要改变redux状态,如果你想这样分配,你需要处理克隆:clonedArray[foundIndex] = action.payload;

答案 1 :(得分:2)

这是数据规范化的理想选择。如果在将数据存储到状态树之前对数据进行规范化,则可以使用新数据有效地替换数据。

此示例直接来自Normalizr

[{
  id: 1,
  title: 'Some Article',
  author: {
    id: 1,
    name: 'Dan'
  }
}, {
  id: 2,
  title: 'Other Article',
  author: {
    id: 1,
    name: 'Dan'
  }
}]

可以通过这种方式规范化 -

{
  result: [1, 2],
  entities: {
    articles: {
      1: {
        id: 1,
        title: 'Some Article',
        author: 1
      },
      2: {
        id: 2,
        title: 'Other Article',
        author: 1
      }
    },
    users: {
      1: {
        id: 1,
        name: 'Dan'
      }
    }
  }
}

规范化的优势是什么?

您可以提取所需状态树的确切部分。

例如 - 您有一个包含有关文章信息的对象数组。如果要从该数组中选择特定对象,则必须遍历整个数组。最坏的情况是数组中不存在所需的对象。为了解决这个问题,我们将数据标准化。

要规范化数据,请将每个对象的唯一标识符存储在单独的数组中。我们将该数组称为results

result: [1, 2, 3 ..]

将对象数组转换为具有键id的对象(请参阅第二个片段)。将该对象称为entities

最终,要使用id 1访问对象,只需执行此操作 - entities.articles["1"]

如果您想用新数据替换旧数据,可以执行此操作 -

entities.articles["1"] = newObj;

答案 2 :(得分:0)

使用数组的原生拼接方法:

/*Find item index using lodash*/
var index = _.indexOf(currentPeople, _.find(currentPeople, {id: 1}));

/*Replace item at index using splice*/
arr.splice(index, 1, {id:1, name:'Mark', email:'mark@email.com'});