React中setState是同步还是异步的?

React setState是同步还是异步的?

class IndexPage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      val: 0
    };
  }
  componentWillMount() { // 组件挂载前触发

  }
  componentDidMount() {

    this.setState({ val: this.state.val + 1 })
    console.log(this.state.val) // 0

    this.setState({ val: this.state.val + 1 })
    console.log(this.state.val) // 0

    setTimeout(() => {
      this.setState({ val: this.state.val + 1 })
      console.log(this.state.val) // 2

      this.setState({ val: this.state.val + 1 })
      console.log(this.state.val) // 3

    }, 0)
  }
  shouldComponentUpdate(nextProps, nextState) { 
      // 组件Props或者state改变时触发,true:更新,false:不更新
    return true
  }
  componentWillUpdate(nextProps, nextState) { // 组件更新前触发

  }
  componentDidUpdate() { // 组件更新后触发

  }
  componentWillUnmount() { // 组件卸载时触发

  }
  render() {
      const { val }=this.state;
      console.log(val, '哈哈') // 0 1 2 3
    return (
      <div>
        我是首页{val}
      </div>);
  }
}
  • react内部为了优化setState()的批处理,会对setState()进行合并,并且对相同属性的设置只保留最后一次的设置,类似于函数Object.assign()。
  • 在 React 的 setState 函数实现中,会根据一个变量 isBatchingUpdates 判断是直接更新 this.state 还是放到一个updateQueue中延时更新,而 isBatchingUpdates 默认是 false,表示 setState 会同步更新 this.state;但是,有一个函数 batchedUpdates,该函数会把 isBatchingUpdates 修改为 true,而当 React 在调用事件处理函数之前就会先调用这个 batchedUpdatesisBatchingUpdates修改为true,这样由 React 控制的事件处理过程 setState 不会同步更新 this.state,而是异步的。

结合上面分析的,钩子函数中的 setState 无法立马拿到更新后的值,所以前两次都是输出0,当执行到 setTimeout 里的时候,前面两个state的值已经被更新,由于 setState 批量更新的策略, this.state.val 只对最后一次的生效,为1,而在 setTimmout 中 setState 是可以同步拿到更新结果,所以 setTimeout 中的两次输出2,3,最终结果就为 0, 0, 2, 3 。

setState({},()=>{})参数

  componentDidMount() {
    this.setState({ val: this.state.val + 1 }, () => {
      console.log(this.state.val, 'www') // 1
    })
    console.log(this.state.val) // 0
  }
  • 传递对象:批处理,对相同变量进行的多次处理会合并为一个,并以最后一次的处理结果为准。
  • 传递函数:链式调用,React 会把我们更新 state 的函数加入到一个队列里面,然后,按照函数的顺序依次调用,不会合并为一次。同时,为每个函数传入 state 的前一个状态,这样,就能更合理的来更新我们的 state 了,该函数有两个参数prevState和props。

总结:

异步的情况

由React控制的事件处理函数,以及生命周期函数调用setState时表现为异步 。大部分开发中用到的都是React封装的事件,比如onChange、onClick、onTouchMove等(合成事件中)以及钩子函数中,这些事件处理函数中的setState都是异步处理的。

同步的情况:

React控制之外的事件中调用setState是同步更新的。比如原生js绑定的事件,setTimeout/setInterval,ajax,promise.then内等 React 无法掌控的 APIs情况下,setState是同步更新state的。

原理:

根据isBatchingUpdates来判断是否批量更新,如果当前setState命中了batchUpdate机制,就会异步执行,如果未能命中,则会同步执行

参考地址

掘金
csdn


   转载规则


《React中setState是同步还是异步的?》 echo丶若梦 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
将setState异步操作改为同步 将setState异步操作改为同步
异步的情况由React控制的事件处理函数,以及生命周期函数调用setState时表现为异步 。大部分开发中用到的都是React封装的事件,比如onChange、onClick、onTouchMove等(合成事件中)以及钩子函数中,这些事件处
2021-04-06
下一篇 
html中前端页面预览pdf文档的6种方法 html中前端页面预览pdf文档的6种方法
前端需要查看pdf文件的方法: 1. a链接查看。这种方法就需要人为点击链接才会显示pdf文件内容,是显示还是下载就决定于浏览器的解释方法了。 <!DOCTYPE html> <html lang="en"> <head>
2021-03-30 echo丶若梦
  目录