之前面试的时候问到setState
调用之后state值是否会立即改变,答案是否定的,借此来讲述一波自己在学习之后对 setState
机制
首先由代码引入
class ComponentsetState extends Component {
constructor() {
super();
this.state={
name: "heheyuanqing",
age: 18
};
}
changeState = function () {
this.setState({
name: "superman",
age: 25
});
console.log(this.state);
}
render() {
return (
<div className="parent">
<div>name:{this.state.name}</div>
<div>age:{this.state.age}</div>
<button onClick={this.changeState.bind(this)}>修改</button>
</div>
)
}
}

接着继续看,将console
输出作为setState第二个参数
changeState = function () {
this.setState({
name: "superman",
age: 25
},function () {
console.log(this.state);
});
console.log(this.state);
}

最后再看一个,使用setTimeout
调用setState
changeState = function () {
setTimeout(()=>{
this.setState({
name: "superwoman",
age: 25
});
console.log(this.state);
},0);
}

调用setState之后发生的事情:
具体代码可以查看源码
- 将state值/callback放入队列enqueueSetState()/enqueueCallback()
- 在enqueueSetState()函数中:
首先获取组件对象;
接着查看组件的_pendingStateQueue(数组),并且将new state存入;
最后调用enqueueUpdate()
- 在enqueueUpdate()函数中:
首先通过batchingStrategy.isBatchingupdates判断是否处于更新阶段
若true
将待更新组件存入dirtyComponent中
反之,调用batchedUpdates()
- 通过batchedUpdates()发起事务
首先将isBatchingUpdates设置为
true
,进入更新阶段
接着以事务的形式处理:transation.perform()
*wrapper封装了两个函数:
RESET_BATCHED_UPDATES(初始化:[空函数];close:[设置isBatchingUpdates为false,更新结束]);
FLUSH_BATCHED_UPDATES(初始化:[空函数];close:[遍历dirtyComponent,执行runBatchUpdates]);
- runBatchedUpdates
首先调用performUpdateIdNeccessary执行updateComponent,执行生命周期方法;
接着完成执行前的callback(即state中的第二个参数)
了解一下transation
通过wrapper封装方法函数,使用perform开始执行事务,首先执行所有方法的initialize的方法,然后再执行perform的callback函数,最后执行所有方法的close方法

-
setState方法是异步的
在调用setState方法之后,state的值并不是立即改变的,具有延时执行的行为,是不保证同步
-
setState方法存在循环调用的危险
在shouldComponentUpdate、componentWillUpdate中调用setState时最后在updateComponent中会调用shouldComponentUpdate、componentWillUpdate造成循环调用
最后,回到代码
- 在changeState中调用setState后立即输出时,state值没有改变,这是因为在调用
setState时isbatchingUpdates=true,因此被放入dirtyComponent中没有立即执行;
在setTimeout内调用setState时,没有前置batchUpdate 的调用所以isbatchingUpdates = false立即执行
参考链接:
https://zhuanlan.zhihu.com/p/20328570
https://blog.csdn.net/u013510838/article/details/59486772#t0
网友评论