简体   繁体   English

如何在不变异的情况下更新对象数组的嵌套数组的状态

[英]How to update state of nested array of array of objects without mutating

I am tryin to update the state of nested array of objects, for instance add to results[0].rooms[2] -> loop rooms -> and add to each object room.sunday.flag 我正在尝试更新对象的嵌套数组的状态,例如添加到results [0] .rooms [2]->循环房间->并添加到每个对象room.sunday.flag

array of results:
results:  [ 
  { dates:
  { weekstart: 2018-08-26T04:00:00.000Z,
    weekend: 2018-09-02T03:59:59.000Z,
    daysofweek: [Array] },
 need: [ '103', '204', '12', '234', '34', '555', '44' ],
 backorder:
  [ '100', '102', '150', '403', '344', '12', '3434', '23', '44' ],
 _id: 5b7b139465c29145d8d69ac2,
 iscurrent: true,
 isnext: false,
 rooms: [ [Object], [Object], [Object], [Object] ],
 user: 5b61b782719613486cdda7ec,
 __v: 9 },

 { dates:
  { weekstart: 2018-09-02T04:00:00.000Z,
    weekend: 2018-09-09T03:59:59.000Z,
    daysofweek: [Array] },
 need: [ '12', '13', '55', '45' ],
 backorder: [ '10', '11', '112' ],
 _id: 5b83fdc500b6b6dc493e9bb8,
 iscurrent: false,
 isnext: true,     rooms: [ [Object], [Object], [Object], 
 [Object] ],
 user: 5b61b782719613486cdda7ec,
 __v: 9 } 
 ]

my attempt to change the state without mutating 我试图改变状态而不改变的尝试

   const resultsRooms = [ 
     ...this.state.results[0].rooms ];
        const rooms = resultsRooms.map((room, roomIndex) => 
   {
        room.sunday.flag = true;
   });

   const resultsUpdaye = this.results.forEach((element, index) => {
      if (index === 0) {
            elsment.rooms = rooms;
         }
   });

   this.setState({
            results: resultsUpdaye
   });

any help? 有什么帮助吗? what am i doin wrong 我在做什么错

Your resultsRooms.map is wrong. 您的resultsRooms.map错误。 First of all, it does not return an object. 首先,它不返回对象。 If you use an arrow function and want to return an object, you must enclose it with parentheses. 如果使用箭头函数并要返回对象,则必须用括号将其括起来。

const foo = () => ( { foo: "bar" } );

If you don't do that the function sees {} as a body block. 如果不这样做,该函数会将{}视为主体块。

Your second problem is, map returns an array, does not do operations on items. 您的第二个问题是, map返回一个数组,不对项目执行操作。 So you can't do this: room.sunday.flag = true; 因此,您无法执行以下操作: room.sunday.flag = true;

Here is the working version: 这是工作版本:

const rooms = resultsRooms.map((room, roomIndex) => 
   ( { ...room, sunday: {...room["sunday"], flag: true } } )
);

So, we map the rooms, then return an object with spread syntax. 因此,我们映射了房间,然后返回具有扩展语法的对象。 With ...room we keep the parts of the room other than the sunday object. 使用...room我们保留roomsunday对象以外的其他部分。 With sunday: {...room["sunday"], flag: true } we keep the parts of the sunday other than the flag property. 使用sunday: {...room["sunday"], flag: true }我们保留flag属性以外的sunday其他部分。 Also, actually we don't need to make a copy with: 另外,实际上我们不需要复制以下内容:

const resultsRooms = [ 
     ...this.state.results[0].rooms ];

Since we don't mutate it, with map we are creating a new array. 由于我们不对其进行变异,因此我们使用map创建了一个新数组。 So, here is the last version: 所以,这是最后一个版本:

const rooms = results[0].rooms.map((room, roomIndex) => 
   ( { ...room, sunday: {...room["sunday"], flag: true } } )
);

This part is OK, we don't mutate the state but if you use forEach on results you mutate the original data. 这部分还可以,我们不对状态进行突变,但是如果对results使用forEachresults对原始数据进行突变。 Don't do it. 不要这样

Here is a concise and maybe a cleaner alternative without using forEach . 这是一种简洁的方法,也许是一种更清洁的选择,而无需使用forEach

const newRooms = results[0].rooms.map( room =>
    ( { ...room, sunday: {...room["sunday"], flag: true } } )
  );

const newItem = { ...results[0], rooms: newRooms };
const newResults = Object.assign([], results, { 0: newItem } );

Update after comments 评论后更新

I used Object.assign here to replace the item without mutating the original array. 我在这里使用Object.assign来替换项目,而无需更改原始数组。 When using React (also if you prefer to use with React, this applies to Redux also) we should avoid mutating our data, namely our state. 当使用React时(同样如果您更喜欢与React一起使用,这也适用于Redux),我们应该避免改变我们的数据,即我们的状态。 So, when you plan to change something in the state you should do it in proper ways. 因此,当您打算在状态下更改某些内容时,应该以正确的方式进行操作。 Your question actually indicates that: "without mutating". 您的问题实际上表明:“无变异”。 This is why I used Object.assign here. 这就是为什么我在这里使用Object.assign原因。

I could choose other methods like: 我可以选择其他方法,例如:

const newResults = results.slice();
newResults[ 0 ] = newItem;

or 要么

const newResults = [ ...results ];
newResults[ 0 ] = newItem;

Those are ok just for replacing the item as a whole . 这些可以代替整个物品 What do I mean here? 我这是什么意思 slice and spread syntax does not create deep copies, they just do shallow copies. slicespread syntax不会创建深层副本,而只会创建浅层副本。 If you change a property of an object in the newly created array, the original one also mutates. 如果您在新创建的数组中更改对象的属性,则原始对象也会发生变化。 This also applies to objects when we change nested properties. 当我们更改嵌套属性时,这也适用于对象。 Actually, original source is objects here. 实际上,原始来源是这里的对象。

Here is an example array: 这是一个示例数组:

const arr = [
  { id:1, name:"foo" },
  { id:2, name:"bar" },
  { id:3, name:"baz" },
];

and an example item to change for index 2 (last item here); 以及要更改索引2的示例项(此处为最后一项);

const newItem = { id: 100, name: "change" };

const newArr = [ ...arr ];
arr[ 2 ] = newItem;

This is ok since we change a whole object here. 可以,因为我们在这里更改了整个对象。 Let's see: 让我们来看看:

 const arr = [ { id:1, name:"foo" }, { id:2, name:"bar" }, { id:3, name:"baz" }, ]; const newItem = { id: 100, name: "change" }; const newArr = [ ...arr ]; newArr[ 2 ] = newItem; console.log("new array", newArr ); console.log( "original array", arr ); 

Original one does not change. 原件不变。 But if we do this: 但是,如果我们这样做:

newArr[ 2 ].id = 100; // ie, we only want to change the id, right?

Let's see: 让我们来看看:

 const arr = [ { id:1, name:"foo" }, { id:2, name:"bar" }, { id:3, name:"baz" }, ]; const newArr = [ ...arr ]; newArr[ 2 ].id = 100; console.log("new array", newArr ); console.log( "original array", arr ); 

So, our original array also changed. 因此,我们的原始数组也发生了变化。 Mutation! 突变! If you don't change any property like this you can choose one of all three alternatives. 如果您不更改任何此类属性,则可以选择所有三个选项之一。 But if you change a property you should think something better. 但是,如果您更改属性,则应该考虑一些更好的方法。

 const arr = [ { id:1, name:"foo" }, { id:2, name:"bar" }, { id:3, name:"baz" }, ]; const newArr = Object.assign( [], arr, { 2: { ...arr[ 2 ], id: 100 } } ); console.log("new array", newArr ); console.log( "original array", arr ); 

Duh! h! :) Maybe there are better ways of doing this :) In any case, be very careful about mutating the state. :)也许有更好的方法可以做到这一点:)无论如何,在改变状态时要非常小心。

Just with an object: 仅带有一个对象:

 const obj = { user: { id: 1, name: "foo", } }; const newObj = { ...obj } newObj.user.id = 1000 console.log( "new object", newObj ); console.log( "original object", obj ); 

Ok, this is enough for an explanation :) 好的,这足以解释一下:)

Thank you for the answer. 谢谢你的回答。 I am a bit confused, am I supposed to set the state as follows: this.setState({ results: newResults }); 我有点困惑,我应该将状态设置如下:this.setState({results:newResults});

Yes. 是。

also what if i want to change the state of all results array rooms results[0],results[1],results[2] ..... 如果我想更改所有结果数组房间的状态,结果[0],结果[1],结果[2] .....

Come on, you have a great tool here :) map 来吧,您这里有个很棒的工具:) map

const newResults = results.map( item => {
  const newRooms = item.rooms.map( room =>
    ( { ...room, sunday: {...room["sunday"], flag: true } } )
  );
  const newItem = { ...item, rooms: newRooms };

  return newItem;
})

First, we map the results , for each item, we map rooms and change the data, return the new item. 首先,我们映射results ,对于每个项目,我们都映射rooms并更改数据,然后返回新项目。 So in the end, we get a new array where all its items changed, but again without any mutation. 因此,最后,我们得到了一个新数组,其中所有项目均已更改,但又没有任何突变。

I suggest playing a little bit with map , filter and maybe reduce methods. 我建议您稍微玩一下mapfilter以及reduce方法。 Also looking for spread syntax or if you prefer Object.assign is a plus. 另外,如果您希望使用spread syntax或者您更喜欢Object.assign也可以。

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

相关问题 Redux推送到嵌套数组而不改变状态 - Redux pushing to a nested array without mutating the state 如何在对象的嵌套数组中添加对象而不改变原始源 - how to add object in nested array of objects without mutating original source 如何在不改变数组的情况下更新此状态? - How can I update this state without mutating the array? 合并两个具有内部数组属性的对象,而不会在react中改变状态 - Merging two objects with inner array properties without mutating the state in react 如何更新从嵌套对象的状态数组映射的单个嵌套组件,而不重新渲染所有内容? - How to update individual nested components mapped from a state array of nested objects, without re-rendering everything? 如何在反应 state 中更新嵌套对象数组中的数组? - How to update the array in nested array of objects in react state? 如何在不更改原始数组的情况下过滤嵌套数组? - How can I filter a nested array without mutating the original array? 交换数组中的对象而不改变数组 - Swap objects in the array without mutating the array 为什么map()在嵌套数组中改变原始对象? - why map() is mutating original objects in a nested array? React 过滤状态而不改变数组 - React Filter the state without mutating the array
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM