this.setState为什么不同步更新?
想要了解这个话题,只需要弄清楚下面三个问题,就明明白白了
1 this.setState()本身是同步的还是不同步的?
首先明确一点,setState 其实本身执行的过程和代码都是同步的
2 是什么造成了this.setState()的不同步?
React的批处理更新(batch the updates)。
React为了优化性能,setState()执行时会判断变量isBatchingUpdates的值是true or false, 然后决定是同步更新还是批量更新(从isBatchingUpdates这个变量名就可以直观的看出)
3 那this.setState()什么时候同步,什么时候不同步?
由于isBatchingUpdates默认值是false,即默认是不批量更新的,是立即执行的,是同步的。
但如果this.setState在React合成事件/钩子函数中,React会通过batchedUpdates()这个函数将isBatchingUpdates变成true,即批量更新的,不同步的。
所以主要看调用this.setState()的函数有没有被React包装过,如果没经过React包装(not managed by ReactJS), isBatchingUpdates就不会从false变为true,就是同步更新的(这是我自己白话总结的,大概这个意思,可能表达不是很准确=.=)
举个栗子
分别用两种方法绑定button的click事件,点击button的时候,改变state的值
改变state的方法是同样的, 封装为changeState:
constructor(props) {
super(props);
this.state = {
type: 'origin', // 原始值为 origin
};
}
changeState = e => {
console.log('prev state:', this.state.type);
this.setState({
type: 'changed', // 改变后为 changed
});
console.log('current state:', this.state.type);
};
a. 通过React合成事件onClick
render() {
console.log('render');
return (
<Button onClick={this.changeState}>改变state</Button>
);
}
点击按钮,控制台打印结果:
说明不是同步更新的
(在输出 current state的地方,this.setState()并未执行,之后执行了才render)
b. 通过原生onclick事件
componentDidMount = e => {
const dom = document.getElementById('btn');
dom.addEventListener('click', this.changeState);
}
render() {
console.log('render');
return (
<Button id="btn">改变state</Button>
);
}
控制台打印结果:
说明是同步更新的
(在输出prev state 之后,遇到this.setState()就立即执行了,state更新之后就触发了render,然后才输出current state)
觉得有用请点赞!
觉得有问题请留言~
这部分主要参考了这两篇文章:
setstate-state-mutation-operation-may-be-synchronous-in-reactjs
React中setState 什么时候是同步的,什么时候是异步的?