按我的组件状态保存的数据(片段)如下:
[
{
batchId: 1234,
...
jobRowData: [
{
assignmentId: 12345,
isSelected: false,
...
},
{
assignmentId: 12346,
isSelected: false,
...
}
]
},
{
batchId: 1235,
...
jobRowData: [
{
assignmentId: 12347,
isSelected: false,
...
},
{
assignmentId: 12348,
isSelected: false,
...
}
]
}
]
我要更改isSelected,并使用以下方法进行操作:
handleIsSelectedChangedJob(selectedIdsData){
let jobRowData = this.state.batchRowData.find((x) => {return x.batchId === selectedIdsData.batchId}).jobRowData
let jobRowItemData = jobRowData.find((x) => {return x.assignmentId === selectedIdsData.assignmentId})
jobRowItemData.isSelected = !jobRowItemData.isSelected // do the update
// this.setState({batchRowData: [...this.state.batchRowData]}) // this also works instead of this.forceUpdate()
this.forceUpdate() // how to refresh view according to update 2 lines above ?
}
其中的参数selectedIdsData可能如下所示:
{assignmentId: 12346, batchId: 1234}
我的问题是:除了执行this.forceUpdate()之外,还有其他刷新视图的方法吗?上面的带注释的行也可以完成这项工作,但是它对整个状态对象起作用,而不是对一个更改的属性起作用。
答案 0 :(得分:1)
绝对!您永远不要直接(通过引用)修改状态,而这正是handleIsSelectedChangedJob
内部发生的事情。您必须创建一个新状态并调用setState
:
handleIsSelectedChangedJob({assignmentId, batchId}) {
const dataIndex = this.state.batchRowData.findIndex(x => x.batchId === batchId);
const data = this.state.batchRowData[dataIndex];
const itemIndex = data.jobRowData.findIndex(x => x.assignmentId === assignmentId);
const item = data.jobRowData[itemIndex];
const newItem = {...item, isSelected: !item.isSelected};
const newData = {
...data,
jobRowData: [].concat(
data.jobRowData.slice(0, itemIndex),
newItem,
data.jobRowData.slice(1 + itemIndex)
)
};
this.setState({
batchRowData: [].concat(
batchRowData.slice(0, dataIndex),
newData,
batchRowData.slice(1 + dataIndex)
)
});
}
如您所见,它的代码更多,但是现在它并没有改变状态,只复制了所需的内容。当然,有很多库可以做到这一点。它仍然不是完美的,因为阅读this.state
然后调用this.setState
并不好-使用this.state(state => diff)
会更安全:
handleIsSelectedChangedJob({assignmentId, batchId}) {
this.setState(state => {
const dataIndex = state.batchRowData.findIndex(x => x.batchId === batchId);
const data = state.batchRowData[dataIndex];
// Same as above...
return {
batchRowData: [].concat(
batchRowData.slice(0, dataIndex),
newData,
batchRowData.slice(1 + dataIndex)
)
};
});
}
答案 1 :(得分:1)
这应该可以让您做自己想要做的事情:
handleIsSelectedChangedJob(selectedIdsData){
const _batchRowData = ...this.state.batchRowData;
const batchIndex = _batchRowData.findIndex((x) => x.batchId === selectedIdsData.batchId);
const jobIndex = batchIndex < 0 ? -1 : _batchRowData[batchIndex].jobRowData.findIndex((x) => x.assignmentId === selectedIdsData.assignmentId);
if (batchIndex < 0 || jobIndex < 0) {
return;
}
_batchRowData[batchIndex].jobRowData[jobIndex].isSelected = !batchRowData[batchIndex].jobRowData[jobIndex].isSelected;
this.setState({ batchRowData: [..._batchRowData] });
}