Object 使用Javascript/Lodash替换Redux存储中对象数组中的对象
我在减速器中有一个对象数组,如下所示:Object 使用Javascript/Lodash替换Redux存储中对象数组中的对象,object,reactjs,redux,store,lodash,Object,Reactjs,Redux,Store,Lodash,我在减速器中有一个对象数组,如下所示: [ {id:1, name:Mark, email:mark@email.com}, {id:2, name:Paul, email:paul@gmail.com}, {id:3,name:sally, email:sally@email.com} ] {id:1, name:Eric, email:Eric@email.com} 下面是我的减速机。到目前为止,我可以通过以下方式向currentPeoplereducer添加一个新
[
{id:1, name:Mark, email:mark@email.com},
{id:2, name:Paul, email:paul@gmail.com},
{id:3,name:sally, email:sally@email.com}
]
{id:1, name:Eric, email:Eric@email.com}
下面是我的减速机。到目前为止,我可以通过以下方式向currentPeople
reducer添加一个新对象:
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:Mark, email:mark@email.com},
{id:2, name:Paul, email:paul@gmail.com},
{id:3,name:sally, email:sally@email.com}
]
{id:1, name:Eric, email:Eric@email.com}
我能用新字段替换id为1的对象吗?这是数据规范化的一个很好的候选者。如果在将数据存储到状态树之前对其进行规范化,则可以有效地用新数据替换数据 这个例子是直接从 可以通过这种方式进行规范化-
{
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
结果:[1,2,3..]
并将对象数组转换为具有键作为id
的对象(请参见第二个片段)。将该对象称为实体
最后,要使用id
1访问对象,只需执行以下操作-entities.articles[“1”]
如果要用新数据替换旧数据,可以这样做-
entities.articles[“1”]=newObj代码>这是数据规范化的一个很好的候选者。如果在将数据存储到状态树之前对其进行规范化,则可以有效地用新数据替换数据
这个例子是直接从
可以通过这种方式进行规范化-
{
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
结果:[1,2,3..]
并将对象数组转换为具有键作为id
的对象(请参见第二个片段)。将该对象称为实体
最后,要使用id
1访问对象,只需执行以下操作-entities.articles[“1”]
如果要用新数据替换旧数据,可以这样做-
entities.articles[“1”]=newObj代码>是的,您完全可以按照自己的意愿更新数组中的对象。如果不想更改数据结构,则无需更改数据结构。您可以在减速机上添加这样的箱子:
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关于使用normalizer将数据映射到对象的想法当然是可能的,从技术上讲,使用引用更新用户比执行循环(在完成初始映射之后)更快。但是,如果您想保持数据结构,这种方法将起作用
此外,像这样的映射只是更新对象的多种方法之一,需要浏览器支持Array.prototype.map()。您可以使用lodash indexOf()来查找所需用户的索引(这很好,因为它在成功时会中断循环,而不是像.map那样继续),一旦有了索引,就可以直接使用其索引覆盖对象。但是,请确保不改变redux状态,如果要这样分配,则需要处理克隆:clonedArray[foundIndex]=action.payload代码>是的,您完全可以按照自己的意愿更新数组中的对象。如果不想更改数据结构,则无需更改数据结构。您可以在减速机上添加这样的箱子:
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关于使用normalizer将数据映射到对象的想法当然是可能的,从技术上讲,使用引用更新用户比执行循环(在完成初始映射之后)更快。但是,如果您想保持数据结构,这种方法将起作用
此外,像这样的映射只是更新对象的多种方法之一,需要浏览器支持Array.prototype.map()。您可以使用lodash indexOf()来查找所需用户的索引(这很好,因为它在成功时会中断循环,而不是像.map那样继续),一旦有了索引,就可以直接使用其索引覆盖对象。但是,请确保不改变redux状态,如果要这样分配,则需要处理克隆:clonedArray[foundIndex]=action.payload代码>使用阵列的本机拼接方法:
/*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'});
使用阵列的本机拼接方法:
/*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'});
我选择这个作为答案,因为我仍然需要这种格式,它的工作!只是一个简单的问题,我使用了您的映射示例,它工作得非常完美,但您是否建议使用lodash,因为这需要浏览器支持?这实际上取决于您需要支持哪些浏览器。IE9+和Chrome/SafariFF/Opera都支持Array.map。所以,除非您有特定的浏览器需求支持,比如IE8,否则您应该对array.map很好。有关完整的浏览器支持和旧浏览器的polyfill,请参见MDN页面:。我选择了此作为答案,因为我仍然需要