React:在调用setState之前,当试图以不可变的方式更改状态时,为什么要更改状态



当我试图在React中以不可变的方式更改状态时,它正在更改我调用setstate之前的状态,这让我困惑了3天。

这是我在onClick事件中调用的方法:

share = (indexFolder) => {
console.log(this.state.folderInfo);
const updateFolderInfo = [...this.state.folderInfo];
updateFolderInfo[indexFolder].isProcessing = false; 
//state**is already changed**strong text** when console **
console.log(this.state.folderInfo);
this.setState({
folderInfo : updateFolderInfo,
})
// the setState call do not take effect here 
}

这就是执行方法的地方:

<Folder key={folder._id}
sharing={this.state.folderIsProcessing}
folder={folder} 
delete={() => this.delete(index)}
share={() => this.share(index)} />
//I'm passing share function as props in here ^ , and use it on 
//click event in the Folder component . 

为什么会发生这种情况,有什么建议吗?

这里的问题是,通过执行const updateFolderInfo = [...this.state.folderInfo];,您实际上是在制作folderInfo副本。

这意味着,如果修改updateFolderInfo中的任何对象或数组项,也将修改原始folderInfo数组中的同一对象/数组。

假设folderInfo内部只有JSON,下面是一个使用JSON.stringifyJSON.parse创建深度副本的潜在解决方案:

share = indexFolder => {
const updatedFolderInfo = JSON.parse(JSON.stringify(this.state.folderInfo));
updatedFolderInfo[indexFolder].isProcessing = false; 
this.setState({ folderInfo : updatedFolderInfo });
}

下面是一个简单的例子,向你展示你目前正在做的事情:

array1 = [{id: 1}, {id: 2}, {id: 3}]
array2 = [...array1]
array2[0].id = 100
array2
// [{id: 100}, {id: 2}, {id: 3}]
array1
// [{id: 100}, {id: 2}, {id: 3}]

你可以在这里找到更多关于浅层与深层克隆的信息

您已经将函数绑定到上面的作用域。试着这样改变它。

share = (indexFolder) => {
console.log(this.state.folderInfo);
const updateFolderInfo = [...this.state.folderInfo];
updateFolderInfo[indexFolder].isProcessing = false; 
//state**is already changed**strong text** when console **
console.log(this.state.folderInfo);
this.setState({
folderInfo : updateFolderInfo,
})
// the setState call do not take effect here 
}
<Folder  key={folder._id}
sharing={this.state.folderIsProcessing}
folder={folder} 
delete={this.delete(index)}
share={this.share(index)}
/>

提供的信息太少,但尝试以其他方式使用setState:

share = (indexFolder) => {
this.setState((prevState) => {
const updateFolderInfo = [...prevState.folderInfo];
updateFolderInfo[indexFolder].isProcessing = false; 
return { 
folderInfo : updateFolderInfo
}
}) 
}

关于setState的异步性质:https://medium.com/@were Hamster/bewere-实际-设置状态-is-同步-ce87ef1a9cf3

最新更新