返回博主主页

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为什么不同步更新?

 

posted @   懒惰的星期六  阅读(902)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2018-12-06 Android进程优先级和垃圾回收机制

Welcome to here

主页
点击右上角即可分享
微信分享提示