setState异步真的只是为了性能吗?

简介: 我们在 React 使用 setState时知道,它并不总是异步更新,也可能是同步更新,大家也知道setState使用异步是为累积更新、批量处理、减少调用次数来提升性能,但是大家有没有想过setState的异步更新真的单单是为了性能吗?

前言


我们在 React 使用 setState时知道,它并不总是异步更新,也可能是同步更新,大家也知道setState使用异步是为累积更新、批量处理、减少调用次数来提升性能,但是大家有没有想过setState的异步更新真的单单是为了性能吗?

网络异常,图片无法展示
|


setState API


setState(updater, [callback])
updater
(state, props) => stateChange


updater 函数中接收的 state 和 props 都保证为最新。updater 的返回值会与 state 进行浅合并。


callback

setState() 的第二个参数为可选的回调函数,它将在 setState 完成合并并重新渲染组件后执行。通常,我们建议使用 componentDidUpdate() 来代替此方式。


异步


setState将对组件state的更改排入队列,并通知React需要使用更新后的state重新渲染组件及其子组件。为了更好的性能,setState并不是立即进行更新,而是使用批量推迟更新。


看几个异步的例子,这些都是经常出现在面试中的代码例子(源码测试

class Test extends Component {
  state = {
    count: 0
  };
  componentDidMount() {
    this.setState({
        count: 1
      }, () => {
        console.log(this.state.count); //1
      }
    );
    console.log(this.state.count); // 0
  }
  render() {}
}
class Test extends Component {
  state = {
    count: 0
  };
  componentDidMount() {
    this.setState(
      {
        count: this.state.count + 1
      },
      () => {
        console.log(this.state.count); // 1
      }
    );
    this.setState(
      {
        count: this.state.count + 1 // 这里的count还是0,并不会拿到更新后的count
      },
      () => {
        console.log(this.state.count); // 1 
      }
    );
  }
  render() {}
}
class Test extends React.Component {
  state = {
    count: 0
  };
  componentDidMount() {
    this.setState(
      (preState) => {
        console.log(preState.count); // 0
        return {
          count: preState.count + 1
        };
      },
      () => {
        console.log(this.state.count); // 2
      }
    );
    this.setState(
      (preState) => {
        console.log(preState.count); // 1
        return {
          count: preState.count + 1
        };
      },
      () => {
        console.log(this.state.count); // 2
      }
    );
  }
  render() {
    return <div>1</div>;
  }
}码


当调用setState函数时,就会把当前的操作放入到队列中,React 根据内容合并state数据,完成之后在逐一执行回调,根据结果去更新需求DOM,触发渲染。这里采用的是异步的方法,根据说法是异步是为了累积更新,批量处理,减少渲染次数,提升性能。


难道同步就不能累积更新、批量处理了吗


这里其实我们换一个角度来想想,难道同步就不能累积更新、批量处理了吗?难道同步就不能减少渲染次数,提升性了吗?

网络异常,图片无法展示
|


这个问题其实不止我有疑问,很早之前有大佬就已经在Issues上有提出这个问题:

网络异常,图片无法展示
|


当然在这个 Issues 下面 gaearon 大佬回复了这个问题:


网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|


回答的比较长,大体总结了两个方面:


1. 保持一致性


如果改为同步更新的方法,虽然setState是同步的,但是props不是。


2. 为后续的架构升级启用并发更新


为了完成一部的渲染,React会在触发 setState 的时候更新数据来源分配不同的优先级。这些数据的来源有:事件回调句柄、动画效果等,在根据优先级并发处理,提升渲染性能。



目录
相关文章
|
前端开发
setState异步问题
setState异步问题
70 0
|
前端开发 JavaScript
你理解的setState异步是对的吗?
你理解的setState异步是对的吗?
131 0
|
前端开发 JavaScript
setState()异步 同步
setState()异步 同步
|
前端开发
前端学习案例-this.setState是同步还是异步
前端学习案例-this.setState是同步还是异步
104 0
前端学习案例-this.setState是同步还是异步
|
前端开发
前端学习案例1-this.setstate是同步和异步
前端学习案例1-this.setstate是同步和异步
86 0
前端学习案例1-this.setstate是同步和异步
|
前端开发 JavaScript
这一次彻底搞懂React中的setState在更新状态是同步还是异步的?
这一次彻底搞懂React中的setState在更新状态是同步还是异步的?
709 0
这一次彻底搞懂React中的setState在更新状态是同步还是异步的?
|
前端开发
react中setState是同步还是异步
react中setState是同步还是异步
116 0
|
前端开发 JavaScript
React 中 setState 什么时候是同步的,什么时候是异步的
React 中 setState 什么时候是同步的,什么时候是异步的
168 0
|
前端开发 JavaScript
react的setState是异步还是同步
react的setState是异步还是同步
107 0
|
9月前
|
JavaScript 前端开发
揭秘 `nextTick`:解决异步回调的利器(上)
揭秘 `nextTick`:解决异步回调的利器(上)
揭秘 `nextTick`:解决异步回调的利器(上)

热门文章

最新文章