我可能会遗漏一些东西。我知道setState
在React中是异步的,但我似乎仍有这个问题。
想象一下,当用户点击我的应用程序上的任何按钮时,下面是一个处理程序
1. ButtonHandler()
2. {
3. if(!this.state.flag)
4. {
5. alert("flag is false");
6. }
7. this.setState({flag:true});
8.
9. }
this.setState({flag:true})
被执行,但是第二次处理程序被调用时,从前一次调用到状态的更改尚未反映 - - 并this.state.flag
返回false
。setState(function(prevState, props){..})
可让您访问之前的状态,但如果我只想阅读第3行的状态并且未设置它,该怎么办?答案 0 :(得分:3)
正如您所正确指出的,要根据以前的状态设置状态,您需要使用函数重载。
我知道setState(function(prevState,props){..})可以让你访问以前的状态
所以你的例子看起来像这样:
handleClick() {
this.setState(prevState => {
return {
flag: !prevState.flag
};
});
}
如果我只想阅读第3行的状态而不设置它会怎么样?
让我们回想一下为什么你想要这样做。
如果您想执行副作用(例如,登录到控制台或启动AJAX请求),那么正确的地方就是componentDidUpdate
生命周期方法。它还使您可以访问以前的状态:
componentDidUpdate(prevState) {
if (!prevState.flag && this.state.flag) {
alert('flag has changed from false to true!');
}
if (prevState.flag && !this.state.flag) {
alert('flag has changed from true to false!');
}
}
这是使用React状态的预期方法。您让React管理状态,并且在设置时不要担心。如果要根据以前的状态设置状态,请将函数传递给setState
。如果要根据状态更改执行副作用,请比较componentDidUpdate
中的上一个和当前状态。
当然,作为最后的手段,您可以保持一个独立于状态的实例变量。
答案 1 :(得分:1)
state和props应该指示组件渲染所需的东西。只要状态和道具发生变化,就会调用React的渲染。
在您的情况下,您会根据需要特定时间的用户互动造成副作用。在我看来,一旦你退出渲染 - 你可能想重新考虑state
和props
并坚持一个同步的常规实例属性。
只需将this.state.flag
更改为this.flag
,然后使用分配而不是setState
进行更新。那样你
你可以解决这个问题。我为此编写了代码,但我宁愿不在这里发布,所以人们不会使用它:)
last
的promisified setState可以为您提供所需的保证。以下是使用此类代码的方式:
explicitlyNotShown({x: 5}).then(() => {
// we are guaranteed that this call and any other setState calls are done here.
});
(注意:对于MobX,这不是问题,因为状态更新是同步的。)