为什么 React 使用 createRoot 和 ReactDOM.render 对于 setState 有不同的同步和异步行为?

问题描述 投票:0回答:1

关于以下代码:

import React from "react";

export default class App extends React.Component {
  state = {
    count: 0
  };
  componentDidMount() {
    this.setState({ count: this.state.count + 1 });
    console.log(this.state.count);
    this.setState({ count: this.state.count + 1 });
    console.log(this.state.count);
    setTimeout(() => {
      this.setState({ count: this.state.count + 1 });
      console.log(this.state.count);
      this.setState({ count: this.state.count + 1 });
      console.log(this.state.count);
    }, 0);
  }
  render() {
    return "123";
  }
}

如果使用 ReactDOM.render 日志将是 0,0,2,3,但对于 createRoot 日志将是 0,0,1,1,谁能帮忙解释一下原因?

javascript reactjs react-dom
1个回答
0
投票

ReactDOM.render 和 createRoot 之间行为差异的原因是 React 出于性能原因安排更新和批处理它们的方式。

使用 ReactDOM.render,更新是同步处理的,并且 componentDidMount 中发生的状态变化将被一起批处理。因此,当状态在 componentDidMount 中更新两次时,控制台日志将输出 0,然后再次输出 0,因为这两次状态更新是一起批处理的。

然而,对于 createRoot,React 使用不同的更新批处理策略。在这种情况下,componentDidMount 中的初始状态更新将与 setTimeout 回调中的第一个 setState 调用一起被批处理,因为它们发生在同一个“批处理窗口”中。这意味着控制台日志将输出 0,然后再次输出 0,因为这些更新是一起批处理的。然后,在下一个“批处理窗口”处理完 setTimeout 回调后,接下来的两个状态更新将被一起批处理,并导致控制台日志输出 1,然后再次输出 1。

简而言之,ReactDOM.render 和 createRoot 之间的行为差异是由于 React 出于性能原因安排更新和批处理它们的方式不同。

© www.soinside.com 2019 - 2024. All rights reserved.