官网中说 react setState()方法 状态更新可能是异步的
官网详情移步:https://react.docschina.org/docs/state-and-lifecycle.html
React 可以将多个setState() 调用合并成一个
调用来提高性能。
因为 this.props 和 this.state 可能是异步更新的,你不应该依靠它们的值来计算下一个状态。
// Wrong 此代码`可能`无法更新计数器:
this.setState({
counter: this.state.counter + this.props.increment,
});
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
React 中 setState 什么时候是同步的,什么时候是不同步的?
回答:
在React中,如果是
由React引发的事件处理
(比如:onClick),调用setState不会同步更新this.state;
绕过React引发的事件处理
(比如: addEventListener直接添加、setTimeout/setInterval 产生的异步调用),调用setState会同步更新this.state;
原因:
在React的setState的函数实现中,根据变量isBatchingUpdates
判断是否立即更新this.state。值为false则立即更新。
在调用 由React引发的事件处理 之前,会调用batchedUpdates
函数,将isBatchingUpdates的值修改为true,也就是不同步更新this.state。
观察下面代码的输出 (React setState)
class Example extends React.Component {
constructor() {
super();
this.state = {
val: 0
};
}
componentDidMount() {
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 1 次 log ---- 0
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 2 次 log ---- 0
setTimeout(() => {
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 3 次 log ---- 2
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 4 次 log ---- 3
}, 0);
}
render() {
return null;
}
};
-
第 1 次 log, 第 2 次 log 都是在
React自身的生命周期中
,调用之前触发batchedUpdates
函数,isBatchingUpdates
为true,所以不会立即更新this.state,而是加入了脏组件
。 -
两次 setState 时,获取到 this.state.val 都是 0,所以执行时都是将 0 设置成 1,在 react 内部会被合并掉,只执行一次。设置完成后 state.val 值为 1。
-
setTimeout
时,isBatchingUpdates为false,所以会立即更新this.state。