pub*_*t33 1 javascript state setstate reactjs react-redux
我正在尝试更新嵌套对象数组的状态,例如添加到 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 }
]
Run Code Online (Sandbox Code Playgroud)
我试图在不发生变异的情况下改变状态
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
});
Run Code Online (Sandbox Code Playgroud)
有什么帮助吗?我做错了什么
你resultsRooms.map错了。首先,它不返回对象。如果您使用箭头函数并希望返回一个对象,则必须用括号将其括起来。
const foo = () => ( { foo: "bar" } );
Run Code Online (Sandbox Code Playgroud)
如果你不这样做,该函数将被{}视为一个主体块。
你的第二个问题是,map返回一个数组,不对项目进行操作。所以你不能这样做:room.sunday.flag = true;
这是工作版本:
const rooms = resultsRooms.map((room, roomIndex) =>
( { ...room, sunday: {...room["sunday"], flag: true } } )
);
Run Code Online (Sandbox Code Playgroud)
所以,我们映射房间,然后返回一个带有扩展语法的对象。随着...room我们保持的部分room以外的sunday对象。随着sunday: {...room["sunday"], flag: true }我们保持的部分sunday以外的其他flag财产。此外,实际上我们不需要使用以下内容制作副本:
const resultsRooms = [
...this.state.results[0].rooms ];
Run Code Online (Sandbox Code Playgroud)
由于我们不对其进行变异,因此map我们正在创建一个新数组。所以,这是最后一个版本:
const rooms = results[0].rooms.map((room, roomIndex) =>
( { ...room, sunday: {...room["sunday"], flag: true } } )
);
Run Code Online (Sandbox Code Playgroud)
这部分没问题,我们不会改变状态,但如果你使用forEachonresults你会改变原始数据。不要这样做。
这是一个简洁且可能更简洁的替代方案,无需使用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 } );
Run Code Online (Sandbox Code Playgroud)
评论后更新
我Object.assign在这里用来替换项目而不改变原始数组。当使用 React 时(如果你更喜欢使用 React,这也适用于 Redux)我们应该避免改变我们的数据,即我们的状态。因此,当您计划更改状态中的某些内容时,您应该以适当的方式进行。你的问题实际上表明:“没有变异”。这就是我Object.assign在这里使用的原因。
我可以选择其他方法,例如:
const newResults = results.slice();
newResults[ 0 ] = newItem;
Run Code Online (Sandbox Code Playgroud)
或者
const newResults = [ ...results ];
newResults[ 0 ] = newItem;
Run Code Online (Sandbox Code Playgroud)
那些只是为了替换整个项目就可以了。我在这里是什么意思?slice并且spread syntax不创建深拷贝,它们只做浅拷贝。如果在新创建的数组中更改对象的属性,则原始数组也会发生变化。当我们更改嵌套属性时,这也适用于对象。实际上,原始来源是这里的对象。
这是一个示例数组:
const arr = [
{ id:1, name:"foo" },
{ id:2, name:"bar" },
{ id:3, name:"baz" },
];
Run Code Online (Sandbox Code Playgroud)
以及要更改索引 2 的示例项(此处为最后一项);
const newItem = { id: 100, name: "change" };
const newArr = [ ...arr ];
arr[ 2 ] = newItem;
Run Code Online (Sandbox Code Playgroud)
这是可以的,因为我们在这里更改了整个对象。让我们来看看:
const foo = () => ( { foo: "bar" } );
Run Code Online (Sandbox Code Playgroud)
原版不变。但是如果我们这样做:
newArr[ 2 ].id = 100; // ie, we only want to change the id, right?
Run Code Online (Sandbox Code Playgroud)
让我们来看看:
const rooms = resultsRooms.map((room, roomIndex) =>
( { ...room, sunday: {...room["sunday"], flag: true } } )
);
Run Code Online (Sandbox Code Playgroud)
所以,我们原来的数组也发生了变化。突变!如果您不更改任何这样的属性,您可以选择所有三个选项之一。但是如果你改变一个属性,你应该考虑更好的事情。
const resultsRooms = [
...this.state.results[0].rooms ];
Run Code Online (Sandbox Code Playgroud)
呸!:) 也许有更好的方法可以做到这一点 :) 在任何情况下,都要非常小心地改变状态。
只需一个对象:
const rooms = results[0].rooms.map((room, roomIndex) =>
( { ...room, sunday: {...room["sunday"], flag: true } } )
);
Run Code Online (Sandbox Code Playgroud)
好的,这足以解释了:)
谢谢你的回答。我有点糊涂了,我是不是应该将状态设置如下: this.setState({ results: newResults });
是的。
如果我想更改所有结果数组房间的状态 results[0],results[1],results[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;
})
Run Code Online (Sandbox Code Playgroud)
首先,我们映射results,对于每个项目,我们映射rooms并更改数据,返回新项目。所以最后,我们得到了一个新的数组,其中所有的元素都发生了变化,但同样没有任何变化。
我建议玩一点map,filter也许还有reduce方法。也在寻找spread syntax或者如果你喜欢Object.assign是一个加号。
| 归档时间: |
|
| 查看次数: |
3307 次 |
| 最近记录: |