setState执行机制

setState 是 React 类组件中用于更新组件状态的方法。根据执行的上下文环境,setState 的行为可能会表现出异步或同步的特性。具体区别如下:

1. 为什么 React setState 是异步的?

React 的 setState 并不会立刻更新 state 和重新渲染组件,而是批量更新。这是为了性能优化,避免频繁的 DOM 操作。
React 会将多次 setState 调用合并成一个更新操作,从而减少重渲染的次数。 React 的批量更新机制在 React 合成事件 和 生命周期方法 中会生效,这时 setState 是异步的。

2. 什么时候 setState 是异步的?

在 React 合成事件和生命周期方法中 React 合成事件和生命周期方法由 React 管理,它们会触发 setState 的批量更新机制。
在这些场景中,setState 是异步的,state 不会立即更新。

import React, { Component } from 'react';

class TestComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleClick = () => {
    console.log('Before setState:', this.state.count); // 输出 0

    this.setState({ count: this.state.count + 1 });
    console.log('After setState:', this.state.count); // 还是输出 0

    // 由于 setState 是异步的,state 还未更新
  };

  render() {
    return <button onClick={this.handleClick}>Click Me</button>;
  }
}

export default TestComponent;

解释:

• 在 handleClick(React 合成事件)中调用 setState,state 不会立即更新,React 会将多个 setState 调用合并处理。

• 访问 this.state.count 时,输出的还是旧值。

3. 什么时候 setState 是同步的?

在 setTimeout 或 原生 DOM 事件 中,React 并不接管这些事件,也就无法进行批量更新,因此 setState 会表现为同步的。

import React, { Component } from 'react';

class TestComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleTimeout = () => {
    setTimeout(() => {
      console.log('Before setState:', this.state.count); // 输出 0

      this.setState({ count: this.state.count + 1 });
      console.log('After setState:', this.state.count); // 输出 1
    }, 0);
  };

  handleNativeEvent = () => {
    document.getElementById('btn').addEventListener('click', () => {
      console.log('Before setState:', this.state.count); // 输出 0

      this.setState({ count: this.state.count + 1 });
      console.log('After setState:', this.state.count); // 输出 1
    });
  };

  render() {
    return (
      <div>
        <button onClick={this.handleTimeout}>SetTimeout</button>
        <button id="btn" onClick={this.handleNativeEvent}>Native Event</button>
      </div>
    );
  }
}

export default TestComponent;

解释:

1.  setTimeout 内调用 setState:

  • setTimeout 是原生异步 API,React 无法接管它的上下文,因此不会执行批量更新。

   • setState 在 setTimeout 中是同步的,state 立即更新。  

2.  原生 DOM 事件内调用 setState:

  • 直接使用 addEventListener 添加的事件是原生事件,React 也无法接管。

  • 在这种情况下,setState 是同步的,state 立即更新。

4. 总结

 5. 如何在异步 setState 后获取最新的 state?

使用 setState 的回调函数: React 提供了一个 setState 的回调参数,它会在 state 更新完毕后执行。

this.setState({ count: this.state.count + 1 }, () => {
  console.log('Updated State:', this.state.count);
});

 

posted @ 2024-12-18 11:13  行走的蒲公英  阅读(13)  评论(0编辑  收藏  举报