关于React的setState异步更新问题

1. 同一个生命周期里,多个setState()会只执行最后一个,而放入setTimeout()中的异步函数中的setState()有几个便执行几个;

componentDidMount() {
        this.setState({
            val: this.state.val+1
        }, () => console.log(this.state.val));  // setState()是异步更新,所以第二个是更新后的回调函数,如果回调成功,可以打印出回调后的state
        console.log(this.state.val);
        this.setState({
            val: this.state.val+1
        }, () => console.log(this.state.val));
        console.log(this.state.val);
        setTimeout(() => {
            this.setState({
                val: this.state.val+1
            });
            console.log(this.state.val);
            this.setState({
                val: this.state.val+1
            });
            console.log(this.state.val);
        }, 0)
    }
执行结果:0,0,1,1,2,3

源码解释:

setState通过enqueueUpdate()方法执行state更新,那么需要知道enqueueUpdate()方法的内部实现:

function enqueueUpdate(component) {
            ensureInjected();
            // 如果不处于批量更新模式,那么将遍历dirtyComponents,调用updateComponent, 更新states/props
            if (!batchingStrategy.isBatchingUpdates) {
                batchingStrategy.batchedUpdates(enqueueUpdate, component);
                return;
            }
            // 如果处于批量更新模式,则将该组件保存在dirtyComponents中
            dirtyComponents.push(component);
        }
        
        var ReactDefaultBatchingStrategy = {
            isBatchingUpdates: false,
            batchedUpdates: function (callback, a, b, c, d, e) {
                var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
                ReactDefaultBatchingStrategy.isBatchingUpdates = true;
                if (alreadyBatchingUpdates) {
                    callback(a, b, c, d, e)
                } else {
                    transaction.perform(callback, null, a, b, c, d, e)
                }
            }
        }

在生命周期钩子(react定义的事件机制) componentDidMount()中setState()时,isBatchingUpdates这个属性已经设置为true, 所以会进入批量更新模式,所以两次打印都是0;

在setTimeout()中,没有前置的batchedUpdate调用,所以isBatchingUpdates这个属性为false, 则会进入第一种模式,setState()执行一次,则立即更新一次;

react内部的生命周期钩子的函数走的是react内部的事件机制(事务);在dom绑定的事件,定时器等一些非react事件中的setState()走的是正常的事件机制;

这里说明下:

在按钮原生事件中定义的setState,和定时器效果一样,每次setState都会引起新的render
react事件是合并的成一次render的。

猜你喜欢

转载自www.cnblogs.com/dyh-sjtu/p/9361611.html