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页面:。我选择了此作为答案,因为我仍然需要