簡體   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