详解setState 方法

131 阅读2分钟

为什么要是用 setState

当我们希望通过点击一个按钮从而改变一个文本时,就需要使用到 setState方法,比如:

import React, { Component } from 'react'

export default class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      message: "Hello World"
    }
  }

  render() {
    return (
      <div>
        <h2>{this.state.message}</h2>
        <button onClick={e => this.changeText()}>改变文本</button>
      </div>
    )
  }

 changeText() {
    this.setState({
      message: "文本已经被改变"
    })
  }
}

当我们调用setState时,会重新执行render函数,根据最新的State来创建ReactElement对象;然后再根据最新的ReactElement对象,对DOM进行修改

另外,setState方法是从Component中继承过来的

setState 异步更新

changeText() {
  this.setState({
    message: "文本已经被改变"
  })
  console.log(this.state.message); // Hello World
}

上面代码中再使用 setState 方法后,再打印 message,发现 message 没有被改变,由此可以看到 setState 是异步操作,在执行完setState之后不能够立刻拿到最新的state的结果

为什么要异步更新

设计成异步,可以显著提升性能,如果每次调用 setState都进行一次更新,那么意味着render函数会被频繁调用,界面重新渲染,这样效率是很低的,所以最好的办法是获取到多个更新,然后进行批量的更新 如果同步更新了state,但是还没有执行render函数,那么state和props不能保持同步,这样做会引起很多问题

如何获取更新后的值

1、setState接受两个参数:第二个参数是一个回调函数,这个回调函数会在更新后会执行

changeText() {
  this.setState({
    message: "文本已经被改变"
  }, () => {
    console.log(this.state.message); // 文本已经被改变
  });
}

2、通过生命周期函数 componentDidUpdate

componentDidUpdate(prevProps, provState, snapshot) {
  console.log(this.state.message);
}

同步 or 异步

setState 方法到底是同步还是异步分两种情况

  1. 在组件生命周期或React合成事件中,setState是异步

  2. 在setTimeout或者原生dom事件中,setState是同步

// setTimeout
changeText() {
  setTimeout(() => {
    this.setState({
      message: "文本已经被改变"
    });
    console.log(this.state.message); // 文本已经被改变
  }, 0);
}

// 原生DOM事件
componentDidMount() {
  const btnEl = document.getElementById("btn");
  btnEl.addEventListener('click', () => {
    this.setState({
      message: "文本已经被改变"
    });
    console.log(this.state.message); // 文本已经被改变
  })
}

setState的合并

数据的合并

this.state = {
  name: '小冯',
  age: 19
}

// 通过setState去修改age,是不会对name产生影响的
this.setState({
  age: 18
})

多个setState合并

this.state = {
  counter: 0
}


increment() {
    this.setState({
      counter: this.state.counter + 1
    });

    this.setState({
      counter: this.state.counter + 1
    });

    this.setState({
      counter: this.state.counter + 1
    });
  }

setState 方法执行了3次,但是 counter 的值还是为1,这就是多个state进行合并

如果想要变为3,如何去做:传入一个函数

increment() {
  this.setState((state, props) => {
    return {
      counter: state.counter + 1
    }
  })

  this.setState((state, props) => {
    return {
      counter: state.counter + 1
    }
  })

  this.setState((state, props) => {
    return {
      counter: state.counter + 1
    }
  })
}