这是在React:中调用setState的推荐方法
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
但是,在转到此代码的下一行之前,此格式仍然不等待setState完成:
pressed = () => {
this.setState((prevState, props) => ({
token: 1
}), () => console.warn("TOKEN setState Callback: " + this.state.token));
console.warn("TOKEN before timeout: " + this.state.token);
setTimeout(function() {console.warn("TOKEN after timeout: " + this.state.token)}.bind(this), 500);
...
//rest of function
}
在这种情况下,这是输出的顺序
1. TOKEN setState回调:1
2.超时前的令牌:0
3.超时后的令牌:0。
我不想将//rest of my function
放在回调中,因为它是一个相当长的函数。使函数“异步”并在this.setState
之前加上await
是可行的,但是不建议在各种来源上使用。
为什么我的代码不起作用?如何在超时之前调用TOKEN之前使setState调用完成,而又不改变代码的范围?
谢谢。
答案 0 :(得分:4)
提供回调函数不会导致setState变为同步。相反,您应该将代码放入回调函数中,并在完成设置状态后将调用它。
this.setState((prevState, props) => ({
token: 1
}), () => {
console.warn("TOKEN setState Callback: " + this.state.token);
console.warn("TOKEN before timeout: " + this.state.token);
setTimeout(function() {console.warn("TOKEN after timeout: " + this.state.token)}.bind(this), 500);
//rest of function
});
我不想将//函数的其余部分放在回调中,因为这是一个相当长的函数。
如果希望代码在设置状态之后运行,则将其放入回调中。您可以将其提取到帮助程序方法中,以使其更易于阅读,但是代码的长度不会改变您需要调用的位置。
您的另一个选择是将代码放入componentDidUpdate中,并将其包装在检查令牌中的代码是否已更改:
componentDidUpdate(prevProps, prevState) {
if (prevState.token !== this.state.token) {
console.warn("TOKEN before timeout: " + this.state.token);
setTimeout(function() {console.warn("TOKEN after timeout: " + this.state.token)}.bind(this), 500);
//rest of function
}
}
使函数“异步”并在a.wait之前添加this.setState是可行的,但不建议在各种来源上使用。
不推荐的原因是它依赖于react的实现细节。他们碰巧以如下方式实现setState的批处理:如果您将微任务排队,您将等待足够长的时间来做出反应以完成其工作。但是react无法保证这就是他们实现它的方式。
答案 1 :(得分:1)
从文档中
将setState()视为请求而不是立即命令来更新组件。为了获得更好的感知性能,React可能会延迟它,然后在一次通过中更新几个组件。 React不能保证状态更改会立即应用。
因此,即使您已运行setState,也不会自动更新令牌以供您在函数中使用新值。如果令牌仅在该令牌内部使用,那么我将在其中设置变量以增加令牌并在函数内部专门使用它,然后最后使用this.setState({token: 1})