美文网首页
react - setState

react - setState

作者: heheheyuanqing | 来源:发表于2018-04-14 10:51 被阅读21次

之前面试的时候问到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>
        )
    }

}
点击之后state的值并没有立即发生改变

接着继续看,将console输出作为setState第二个参数

 changeState = function () {
       this.setState({
            name: "superman",
            age: 25
        },function () {
            console.log(this.state);
        });
        console.log(this.state);
    }
使用setState的第二个参数

最后再看一个,使用setTimeout调用setState

changeState = function () {
        setTimeout(()=>{
            this.setState({
                name: "superwoman",
                age: 25
            });
            console.log(this.state);
        },0);
    }
setTimeout实现同步改变
调用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方法

ASCII图
  • 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

相关文章

网友评论

      本文标题:react - setState

      本文链接:https://www.haomeiwen.com/subject/mqdnhftx.html