我正在制作一个桌子规划器应用程序,可以将客人分配到餐桌上。 我在一个名为tabledata的状态下创建了一个对象数组,它将包含如下对象:
this.state = {
tabledata: [
{
name: "Top Table",
guests: ["guest1", "guest2", "guest3"]
},
{
name: "Table One",
guests: ["guest3", "guest4", "guest5"]
}
]
}
然后我创建了一个拖放界面,客人可以在表之间移动。我试图像这样更新状态:
updateTableList (tablename, guest) {
const selectedTableObj = this.state.tabledata.filter((tableObj) => tableObj.name === tablename);
const otherTableObjs = this.state.tabledata.filter((tableObj) => tableObj.name !== tablename);
selectedTableObj[0].guests.push(guest);
const updatedObjectArray = [...otherTableObjs, selectedTableObj];
this.setState({
tabledata: [...otherTableObjs, ...selectedTableObj]
});
}
这样可行但是因为我从状态中删除了selectedTableObj然后将它添加到数组的末尾我在屏幕上得到了一些时髦的结果。更新后的表始终会显示在页面底部(正如您所期望的那样)。
如何更新对象而不更改其在数组中的位置?
答案 0 :(得分:1)
使用Array.findIndex()
查找要更新的表的索引。创建一个新的tabledata
数组。使用Array.slice()
获取更新表之前和之后的项目,并spread将它们添加到新的tabledata
数组中。使用对象扩展创建一个新的表对象,添加更新的guests
数组,并在之前的项之间添加表对象:
代码(未经测试):
updateTableList(tablename, guest) {
this.setState((prevState) => {
const tableData = prevState.tabledata;
const selectedTableIndex = tableData.findIndex((tableObj) => tableObj.name === tablename);
const updatedTable = tableData[selectedTableIndex];
return {
tabledata: [
...prevState.tabledata.slice(0, selectedTableIndex),
{
...updatedTable,
guests: [...updatedTable.guests, guest]
},
...prevState.tabledata.slice(selectedTableIndex + 1)
]
};
});
}
答案 1 :(得分:0)
selectedTableObj[0].guests.push(guest)
直接改变了React中不鼓励的状态。
试试这个:
this.setState((prevState) => {
const newData = [...prevState.tabledata];
// if you pass in `index` as argument instead of `tablename` then this will not be needed
const index = prevState.tabledata.findIndex(table => tableObj.name === tablename);
newData[index] = {
...newData[index],
guests: newData[index].guests.concat([guest]),
};
return { tabledata: newData };
});
您也没有从上一个表中删除guest虚拟机,因此您需要对其进行修改。
答案 2 :(得分:0)
您可以使用Array.reduce
来完成let newState = this.state
// let newState = {...this.state} // in case you want everything immutable
newState.tableData = newState.tableData.reduce((acc, table) =>
if(table.name === tableName) {
return acc.concat({...table, guests: table.guests.concat(newGuest)})
} else {
return acc.concat(table)
}
)