繁体   English   中英

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

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

我正在尝试更新对象的嵌套数组的状态,例如添加到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 } 
 ]

我试图改变状态而不改变的尝试

   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
   });

有什么帮助吗? 我在做什么错

您的resultsRooms.map错误。 首先,它不返回对象。 如果使用箭头函数并要返回对象,则必须用括号将其括起来。

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

如果不这样做,该函数会将{}视为主体块。

您的第二个问题是, map返回一个数组,不对项目执行操作。 因此,您无法执行以下操作: room.sunday.flag = true;

这是工作版本:

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

因此,我们映射了房间,然后返回具有扩展语法的对象。 使用...room我们保留roomsunday对象以外的其他部分。 使用sunday: {...room["sunday"], flag: true }我们保留flag属性以外的sunday其他部分。 另外,实际上我们不需要复制以下内容:

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

由于我们不对其进行变异,因此我们使用map创建了一个新数组。 所以,这是最后一个版本:

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

这部分还可以,我们不对状态进行突变,但是如果对results使用forEachresults对原始数据进行突变。 不要这样

这是一种简洁的方法,也许是一种更清洁的选择,而无需使用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 } );

评论后更新

我在这里使用Object.assign来替换项目,而无需更改原始数组。 当使用React时(同样如果您更喜欢与React一起使用,这也适用于Redux),我们应该避免改变我们的数据,即我们的状态。 因此,当您打算在状态下更改某些内容时,应该以正确的方式进行操作。 您的问题实际上表明:“无变异”。 这就是为什么我在这里使用Object.assign原因。

我可以选择其他方法,例如:

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

要么

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

这些可以代替整个物品 我这是什么意思 slicespread syntax不会创建深层副本,而只会创建浅层副本。 如果您在新创建的数组中更改对象的属性,则原始对象也会发生变化。 当我们更改嵌套属性时,这也适用于对象。 实际上,原始来源是这里的对象。

这是一个示例数组:

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

以及要更改索引2的示例项(此处为最后一项);

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

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

可以,因为我们在这里更改了整个对象。 让我们来看看:

 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 ); 

原件不变。 但是,如果我们这样做:

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

让我们来看看:

 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 ); 

因此,我们的原始数组也发生了变化。 突变! 如果您不更改任何此类属性,则可以选择所有三个选项之一。 但是,如果您更改属性,则应该考虑一些更好的方法。

 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 ); 

h! :)也许有更好的方法可以做到这一点:)无论如何,在改变状态时要非常小心。

仅带有一个对象:

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

好的,这足以解释一下:)

谢谢你的回答。 我有点困惑,我应该将状态设置如下:this.setState({results:newResults});

是。

如果我想更改所有结果数组房间的状态,结果[0],结果[1],结果[2] .....

来吧,您这里有个很棒的工具:) 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;
})

首先,我们映射results ,对于每个项目,我们都映射rooms并更改数据,然后返回新项目。 因此,最后,我们得到了一个新数组,其中所有项目均已更改,但又没有任何突变。

我建议您稍微玩一下mapfilter以及reduce方法。 另外,如果您希望使用spread syntax或者您更喜欢Object.assign也可以。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM