11 | setState 到底是同步的,还是异步的?

从一道面试题说起

import React from "react";
import "./styles.css";
export default class App extends React.Component{
  state = {
    count: 0
  }
  increment = () => {
    console.log('increment setState前的count', this.state.count)
    this.setState({
      count: this.state.count + 1
    });
    console.log('increment setState后的count', this.state.count)
  }
  triple = () => {
    console.log('triple setState前的count', this.state.count)
    this.setState({
      count: this.state.count + 1
    });
    this.setState({
      count: this.state.count + 1
    });
    this.setState({
      count: this.state.count + 1
    });
    console.log('triple setState后的count', this.state.count)
  }
  reduce = () => {
    setTimeout(() => {
      console.log('reduce setState前的count', this.state.count)
      this.setState({
        count: this.state.count - 1
      });
      console.log('reduce setState后的count', this.state.count)
    },0);
  }
  render(){
    return <div>
      <button onClick={this.increment}>点我增加</button>
      <button onClick={this.triple}>点我增加三倍</button>
      <button onClick={this.reduce}>点我减少</button>
    </div>
  }
}

控制台输出

异步的动机和原理——批量更新的艺术

一个完整的更新流程,涉及了包括 re-render(重渲染) 在内的多个步骤。re-render 本身涉及对 DOM 的操作,它会带来较大的性能开销。这正是 setState 异步的一个重要的动机——避免频繁的 re-render每来一个 setState,就把它塞进一个队列里“攒起来”。等时机成熟,再把“攒起来”的 state 结果做合并,最后只针对最新的 state 值走一次更新流程。这个过程,叫作“批量更新”,注意:对于相同属性的设置,React 只会为其保留最后一次的更新。

test = () => {
  console.log('循环100次 setState前的count', this.state.count)  // 0
  for(let i=0;i<100;i++) {
    this.setState({
      count: this.state.count + 1
    })
  }
  console.log('循环100次 setState后的count', this.state.count) // 0
}

 

posted @ 2022-12-29 22:32  哥哦狗子  阅读(31)  评论(0编辑  收藏  举报