setState如何同步,可以视同setTimeout(……, 0)跳出React的setState的事务控制

参考:

React的setState批量更新原理

解决问题:如何让React的setState变为同步

btnClick1

两次同时给state.a加1.在React控制的时候,始终多次运行,只会加一次,而且因为setState不同步,console的输出始终先于setState

 btnClick1=()=>{
        this.setState({
            a: this.state.a + 1
        });
        this.setState({
            a: this.state.a + 1
        });
        console.log('点击时的a的值为:',this.state.a);
    }

btnClick3

两次同时给state.a加1.在React控制的时候,始终多次运行setState,会执行多次,而且因为setState跳出了Reactde异步控制,console的输出就会取到setState之后的值。

 btnClick3 = ()=>{
        setTimeout(() => {
            this.setState({
                a: this.state.a + 1
            });
            this.setState({
                a: this.state.a + 1
            });
            console.log('点击时的a的值',this.state.a);
        },0)
    }


结论(React的setState批量更新原理
异步:React 会先找到我们注册的 vnode 和 vnode 内的对应事件,从而在执行前,先把 isBatchingUpdate这个变量打开。只要我们的方法没完成,由于变量锁的存在,就会一直让我们的修改只停留在更新中状态内,一直不会更新到实际的 state
上。直到我们的方法执行完,事务的后置函数就会关闭我们的 isBatchingUpdate,并执行渲染操作,至此整个批量更新就完成了。
同步:setTimeout 里面会同步是由于 setTimeout会把里面的函数放到下一个宏任务内,这样就刚好跳出了事务的控制,就会显示出同步更新的情况。这里就是Javascript 的 Event-loop 机制;另外,在原生事件中,绕过了React,不会触发isBatchingUpdates变量的改变,所以也会同步进行更新渲染

完整代码:

菜鸟教程提供的运行环境:替换为下列代码,可以再页面和F12控制台(mac:option_command_i)查看运行结果

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>菜鸟教程 React 实例</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>

<div id="example"></div>
<script type="text/babel">
class App extends React.Component{
    constructor(props){
        super(props);
    }
    state = {
        a: 1
    }
    componentDidMount(){
       console.log('a的初始值为:',this.state.a);
    }
    

    btnClick1=()=>{
        this.setState({
            a: this.state.a + 1
        });
        this.setState({
            a: this.state.a + 1
        });
        console.log('点击时的a的值为:',this.state.a);
    }
    
    sState = ()=>{
     this.setState({
            a: this.state.a + 1
        });
    this.setState({
          a: this.state.a + 1
      });
    }
    btnClick2=()=>{
        this.sState();
        console.log('点击时的a的值为:',this.state.a);
    }
    
    btnClick3 = ()=>{
        setTimeout(() => {
            this.setState({
                a: this.state.a + 1
            });
            this.setState({
                a: this.state.a + 1
            });
            console.log('点击时的a的值',this.state.a);
        },0)
    }
    render(){
        return (
        <div>
                <div>hello william</div>
                <button onClick={this.btnClick2}>点击按钮</button>
                <div>{this.state.a}</div>
        </div>
        )
    }
}
ReactDOM.render(
     <App />,
    document.getElementById('example')
);
</script>

</body>
</html>

其它:React之this.setState使用需知注意点 -this.setState为什么不同步更新?

原文地址:https://www.cnblogs.com/sunupo/p/15649376.html