前言
本文已收录在 Github: https://github.com/beichensky/Blog 中,欢迎 Star,欢迎 Follow!
18 版本之前
经典面试题:setState 是同步还是异步
在 react 18
版本之前,在面试中经常会出现这个问题,那么答案又是什么样的呢?
-
在
React
合成事件中是异步的 -
在
hooks
中是异步的 -
其他情况皆是同步的,例如:原生事件、
setTimeout
、Promise
等
看看下面这段代码的执行结果,就知道所言非虚了
class App extends React.Component {
state = {
count: 0
}
componentDidMount() {
this.setState({
count: this.state.count + 1})
console.log(this.state.count);
this.setState({
count: this.state.count + 1})
console.log(this.state.count);
setTimeout(() => {
this.setState({
count: this.state.count + 1})
console.log(this.state.count);
this.setState({
count: this.state.count + 1})
console.log(this.state.count);
});
}
render() {
return <h1>Count: {
this.state.count}</h1>
}
}
有经验的同学肯定都知道,最终的结果是: 0 0 2 3
。
原因就是因为 componentDidMount
中的 setState
是批量更新,在整体逻辑没走完之前,不会进行更新。所以前两次打印结果都是 0,并且将两次更新合并成了一次。
而在 setTimeout
中,脱离了 React
的掌控,变成了同步更新,因为下方的 log
可以实时打印出即时的状态。
此时 React
的内部的处理逻辑我们可以写一段代码简单模拟一下:
-
先声明三个变量,用来记录数据
-
isBatchUpdate
: 判断是否批量更新的标志</
-