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 (
      
{this.state.count}
); } }

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

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

React:setState同步or异步?_第1张图片

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

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

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

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

React:setState同步or异步?_第2张图片

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

th

你可能感兴趣的:(React学习笔记,react.js,react,native,javascript)