setState的理解和用法

1.setState更新状态的两种写法:

 (1). setState(stateChange, [callback])------对象式的setState
            1.stateChange为状态改变对象(该对象可以体现出状态的更改)
            2.callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
                    
    (2). setState(updater, [callback])------函数式的setState
            1.updater为返回stateChange对象的函数。
            2.updater可以接收到state和props。
            4.callback是可选的回调函数, 它在状态更新、界面也更新后(render调用后)才被调用。
总结:
        1.对象式的setState是函数式的setState的简写方式(语法糖)
        2.使用原则:
                (1).如果新状态不依赖于原状态 ===> 使用对象方式 例如:
                    this.setState({msg:"我是修改后的值"})
                (2).如果新状态依赖于原状态 ===> 使用函数方式
                      this.setState(state => ({count:state.count+1}))
                (3).如果需要在setState()执行后获取最新的状态数据, 
                    要在第二个callback函数中读取

2.setState 是同步更新还是异步更新

setState 并不是单纯同步/异步的,它的表现会因调用的场景不同而不同:在React钩子函数及合成事件中,它表现为异步;而在setTimeOut,setInterval等函数中,包括在DOM原生事件中,它都表现为同步。这种差异,本质上是由React事务机制和批量更新机制的工作方式来决定的。

 

在源码中通过isBatchingUpdates 来判断setState是先存进state队列还是直接更新,如果值为true则执行异步操作,为false则直接更新。

那什么情况下 isBatchingUpdates 会为 true 呢?

· 在 React 可以控制的地方,isBatchingUpdates就为 true,比如在 React 生命周期事件和合成事件中,都会走合并操作,延迟更新的策略。

· 在 React 无法控制的地方,比如原生事件,具体就是在 addEventListener 、setTimeout、setInterval 等事件中,就只能同步更新。

 

一般认为,做异步设计是为了性能优化、减少渲染次数,React 团队还补充了两点:

· 保持内部一致性。如果将 state 改为同步更新,那尽管 state 的更新是同步的,但是 props不是。 · 启用并发更新,完成异步渲染。

 

3.如何将同步获取setState处理过后的值呢?

1)可以在回调函数中获取setState处理过后的值。

 add = ()=>{
        // this.setState(state => ({count:state.count+1}))
        this.setState((preState)=>{
            return {count:++preState.count}
        },()=>{//此时setState异步执行
            console.log(this.state.count)//1
        })
    }

2) 可以使用es6中的async await 来实现同步。

 add = async ()=>{
        await this.setState(state => ({count:state.count+1}))
        console.log(this.state.count)//1
    }

3)可以使用setTimeout、setInterval

 add =  ()=>{
        setTimeout(()=>{
            this.setState(state => ({count:state.count+1}))
            console.log(this.state.count)//1
        },0)
    }

注意:如果强行使用同步,就会每次改变状态都会重新render渲染,这样性能就会降低。

 

不停学习,热爱是源源不断的动力。
原文地址:https://www.cnblogs.com/ximenchuifa/p/15066883.html