02-组件化-setState详细使用以及为何异步

68 阅读1分钟

this.setState()怎么更改state的

原理:通过Object.assign将原来的state中字面量对象和setState中的子面量对象进行合并得到的

constructor() {
    super()
    this.state = {
      counter: 0,
      message: 'hello world'
    }
  }
  changeMessage () {
    this.setState({
      message: 'react'
    })
  }
  
  // setState相当于做了 
  this.state = Object.assign({
      counter: 0,
      message: 'hello world'
    }, {
      message: 'react'
    })

setState三种使用方法

方法1: 基本用法

this.setState({
    message: 'hello react'
})

方法2:传一个含有返回值的函数

这样的好处有两个:

  1. 好处1:可以把state的处理逻辑放在一个函数中定义,并返回
  2. 好处2:该函数可以接受原来的state和props作为参数,使得新处理逻辑基于这俩参数进行操作
this.setState((state, props) => {
    return {
        message: state.message + '666'
    }
})

方法3:setState的第二个参数

  • 由于react性能原因,setState是异步的,第二个参数为回调函数,当state值更新之后,自动调用。
  • 适合:依赖更新后state的操作场景

关于setState异步和回调的打印顺序demo

image.png

打印顺序:

image.png

可见:setState异步的,先执行后续同步代码console.log('----')此时的message为老message。 后经过异步setState执行成功后,才执行回调中的console.log('---cbcb---'),此时message为更新后的。

为什么setState是异步的?

github react作者的回答如下:

设计为异步,可以显著提高性能,【批量更新】。

  • 如果每调用一次setState,render函数就会被重新执行,这样界面重新进行diff比对,进而对页面进行重绘回流,这样效率很低。
  • 最好的办法就是,setState异步,多次更新数据,批量更新,只调用一次render。
  • 且由于数据改变快,但是页面渲染慢,同步更新state会导致渲染速度跟不上state速度,导致props和state的不一致