React:setState同步or异步?

引言


setState是‘最熟悉的陌生人’,当你入门React的时候,接触的第一波API里一定有setState-----数据驱动视图。当你项目的数据流乱作一团的时候,始作俑者也往往是setState----工作机制太复杂,文档又不说清楚。

setState 的工作机制渐渐与 React 调和算法并驾齐驱,成了 React 核心原理中区分度最高的知识模块之一。

“神奇时刻”到底何时发生?
state到底是在哪个环节发生了变化呢?
所谓的“恰恰好”又如何界定呢?

关于setState的问题,由下面一段代码说起:

给出一个这样的 App 组件,在它的内部会有如下代码所示的几个不同的 setState 操作:

import React, { Component } from 'react';

export default class App extends Component {
  state = {
    count: 0
  };

  handleIncrement = () => {
    console.log('increment setState前的count', this.state.count);
    this.setState({
      count: this.state.count + 1
    });
    console.log('increment setState后的count', this.state.count);
  };

  handleTriple = () => {
    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);
  };

  handleReduce = () => {
    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>
        <div>{this.state.count}</div>
        <button onClick={this.handleIncrement}>点我增加</button>
        <button onClick={this.handleTriple}>点我增加三倍</button>
        <button onClick={this.handleReduce}>点我减少</button>
      </div>
    );
  }
}

此时有个问题,若从左到右依次点击每个按钮,控制台的输出会是什么样的?

  如果你是一个熟手 React 开发,那么 handleIncrement这个方法的输出结果想必难不倒你——正如许许多多的 React 入门教学所声称的那样,“setState是一个异步的方法”,这意味着当我们执行完 setState 后,state本身并不会立刻发生改变。 因此紧跟在 setState后面输出的 state值,仍然会维持在它的初始状态(0)。在同步代码执行完毕后的某个“神奇时刻”,state才会“恰恰好”地增加到 1。

  但这个“神奇时刻”到底何时发生,所谓的“恰恰好”又如何界定呢?如果你对这个问题搞不太清楚,那么 triple方法的输出对你来说就会有一定的迷惑性——setState一次不好使, setState三次也没用,state 到底是在哪个环节发生了变化呢?

  带着这样的困惑,你决定先抛开一切去看看 handleReduce方法里是什么光景,结果更令人大跌眼镜,reduce 方法里的 setState竟然是同步更新的!这…到底是我们初学 React时拿到了错误的基础教程,还是电脑坏了?
 

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

  在setState 调用之后,都发生了哪些事情?基于截止到现在的专栏知识储备,可能会更倾向于站在生命周期的角度去思考这个问题,得出一个如下图所示的结论:

 从图上我们可以看出,一个完整的更新流程,涉及了包括 re-render(重渲染) 在内的多个步骤。re-render本身涉及对 DOM 的操作,它会带来较大的性能开销。假如说“一次 setState就触发一个完整的更新流程”这个结论成立,那么每一次 setState的调用都会触发一次 re-render,我们的视图很可能没刷新几次就卡死了。这个过程如我们下面代码中的箭头流程图所示:

th
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值