我在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的对象?
答案 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'});