react setState同步更新与异步更新

学习react相关的文档知识,有些过时的信息需要及时校正,比如这个setState的同步&异步更新问题以前也是常见的面试题,在react18之后他的答案又变化了,能力的提升就是踩坑的频次。(⊙o⊙)…

言归正传

举个例子

我们有如下代码,是一个常见的面试题

import * as React from 'react';
export default class App extends React.Component {
  state = {
    name: 'abc',
  };
  componentDidMount() {
      this.setState({ name: 'didmount' });
      console.log(this.state.name);
    setTimeout(() => {
      // setTimeout中调用
      console.log('setTimeout: pre----' + this.state.name);
      this.setState({ name: 'setTimeout' });
      console.log('setTimeout:==== ' + this.state.name);
    }, 0);
    document.getElementById('div2').addEventListener('click', this.increment2);
  }

  increment = () => {
    // 合成事件中调用
    console.log('react increment==== ' + this.state.name);
    this.setState({ name: 'increment' });
    console.log('react event: ' + this.state.name);
  };

  increment2 = () => {
    // 原生事件中调用
    console.log('dom event: ====' + this.state.name);
    this.setState({ name: 'dom event' });
    console.log('dom event: ' + this.state.name);
  };

  render() {
    return (
      <div className="App">
        <h2>couont: {this.state.name}</h2>
        <div id="div1" onClick={this.increment}>
          {React.version}increment1
        </div>
        <div id="div2">click me and increment2</div>
      </div>
    );
  }
}

在React 18 之前,

只在React 事件处理函数中进行批异步更新。
默认情况下,在promise、setTimeout、原生事件处理函数中、或任何其它事件内的更新都是同步的

在React 18 之后

import * as React from 'react';
import * as ReactDom from 'react-dom';
import App from './App';
import { createRoot } from 'react-dom/client';

const rootElement = document.getElementById('root');
// 异步测试 --react18 推荐语法
//createRoot(rootElement).render(<App />);
// 同步测试 --react18 废弃语法
ReactDom.render(<App />, rootElement);

当你用 ReactDom.render 挂载节点的时候会运行得到的效果就是

只在React 事件处理函数中进行批异步更新,其他的 promise、setTimeout、原生事件处理函数中的更新都是同步的
当你用 createRoot(rootElement).render(); 挂载节点的时候,
所有的更新都是异步的。

本文作者:番茄炒蛋
本文地址: https://www.noway.pub/2023/09/07/react_setState/
版权声明:转载请注明出处!