[英]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
我們保留room
除sunday
對象以外的其他部分。 使用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
使用forEach
, results
對原始數據進行突變。 不要這樣
這是一種簡潔的方法,也許是一種更清潔的選擇,而無需使用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;
這些可以代替整個物品 。 我這是什么意思 slice
和spread 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
並更改數據,然后返回新項目。 因此,最后,我們得到了一個新數組,其中所有項目均已更改,但又沒有任何突變。
我建議您稍微玩一下map
, filter
以及reduce
方法。 另外,如果您希望使用spread syntax
或者您更喜歡Object.assign
也可以。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.