React dom outerHTML 好像不对吧?

React dom outerHTML seems not right?

I have created a demo.

演示 url:https://4ikgc.csb.app/

为什么 outerHTML 总是 <h1>abc</h1>

顺便说一句,为什么控制台似乎将所有内容记录两次。

现在console.log的内容是:

render h1: {current: null} undefined
render h1: {current: null} undefined
second abc <h1>abc</h1>
forth abc <h1>abc</h1>
first abc <h1>abc</h1>
first abc <h1>abc</h1>
third hello1 <h1>abc</h1>
third hello1 <h1>abc</h1>
fifth hello2 <h1>abc</h1>
fifth hello2 <h1>abc</h1>
render h1: <h1>​hello3​</h1>​ <h1>abc</h1>
render h1: <h1>​hello3​</h1>​ <h1>abc</h1>

但我认为正确的内容是:

render h1: {current: null} undefined
second abc <h1>abc</h1>
forth abc <h1>abc</h1>
first abc <h1>abc</h1>
third hello1 <h1>abc</h1>
fifth hello2 <h1>abc</h1>
render h1: <h1>​hello3​</h1>​ <h1>hello3</h1>

希望有人能帮助我!非常感谢!

import React from "react";

class Hello extends React.Component {
  constructor(props) {
    super(props);
    this.h1 = React.createRef();
    this.state = {
      name: "abc"
    };
  }
  componentDidMount() {
    this.setState((state, props) => {
      console.log("first", state.name, this.h1.outerHTML);
      return {
        name: "hello1"
      };
    });
    console.log("second", this.state.name, this.h1.outerHTML);
    this.setState((state, props) => {
      console.log("third", state.name, this.h1.outerHTML);
      return {
        name: "hello2"
      };
    });
    console.log("forth", this.state.name, this.h1.outerHTML);
    this.setState((state, props) => {
      console.log("fifth", state.name, this.h1.outerHTML);
      return {
        name: "hello3"
      };
    });
  }
  render() {
    console.log("render h1:", this.h1, this.h1.outerHTML);

    return <h1 ref={ref => (this.h1 = ref)}>{this.state.name}</h1>;
  }
}

export default Hello;

你的 Hello 组件有一个 H1 并且你使用那个 Hello 组件的地方还有另一个 H1

    <div className="App">
      <Hello />
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>

你得到 2 console.logs 的原因是 React 生命周期的工作方式。 render 中的第一个 console.log 发生在组件最初呈现时。组件渲染后反应触发 componentDidUpdate 生命周期方法。

然后,当您在该方法中触发 this.setState 时,它会再次触发 render 的重新渲染。那是你的第二个 console.log。此外,因为在您的特定情况下,您在 componentDidUpdate 中多次设置 this.state 它会触发多个状态更改。

还请注意,在 development 模式下并使用 react strict <React.StrictMode> 时,setState 会被调用两次。这是故意的。它不会在生产中发生。

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootElement
);

参考文献:
https://github.com/facebook/react/issues/12856#issuecomment-390206425

https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects