为什么 componentWillUnmount 之后有 componentDidMount 运行?

Why did componentDidMount run after componentWillUnmount?

我试图找出 componentDidMountcomponentWillUnmount 之间的区别并尝试了以下代码:


class App extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      name: "",
    };
  }

  componentDidMount() {
    console.log("Inside componentDidMount");
  }

  componentWillUnmount() {
    console.log("Inside ComponentWillUnMount");
  }

  render() {
    return (
      <div className="App">
        {console.log("I am in render")}
        <header className="App-header">
          <input
            type="text"
            value={this.state.name}
            onChange={(e) => this.setState({ name: e.target.value })}
            placeholder="enter your name"
          />
          <p>Edit and save to reload.</p>
        </header>
      </div>
    );
  }
}

目前我的理解是

  1. componentDidMount会在组件挂载后调用,只调用一次 即使经过多次重新渲染(如果我在这里错了,请纠正我)
  2. componentWillUnmount 将在组件卸载时调用一次。

但我在控制台中观察到 componentDidMount 在渲染之后被调用,这是预期的,而且在 componentWillUnMount 之后被调用。

我的问题是:

  1. 为什么调用 componentWillUnMount 因为我只有 App 组件,没有其他组件可以渲染,而且我还在第一个屏幕上?为什么要卸载 App 组件,因为我仍然在那个屏幕上,在那里我可以看到 App 组件包含的内容(这是输入)

  2. 为什么 componentDidMount 运行 在 componentWillUnMount 之后?

为什么我们需要在构造函数中使用 props 调用 super()?

Result with Class component

我什至用 useEffect 的功能组件尝试了上面的代码,结果是一样的。

const AppSample = () => {
    useEffect(() => {
        console.log('I am in useEffect');
        return () => {
            console.log("Inside clean up function")
        }
    }, []);

    const [name , setName ] = useState('')

    return  (
        <div>
        {
            console.log(" I am inside render")
        }
            <input value={ name } onChange={(e) => setName(e.target.value)} />
        </div>
    )
}

console.log('I am in running') 被打印两次,即一次在渲染之后,另一次在执行清理函数之后

Result With functional component

解释如下:

componentWillUnmount 当一个组件从 DOM.

被 removed/updated 时调用此方法

这里是生命周期工作原理的详细图表:1

所以你可以看到在第一次渲染之后和 ComponentDidMount 反应之前更新 DOM 并且在这个更新之后 componentWillUnmount 将被触发。

如果你愿意或者我在这里遗漏了什么,我们可以讨论这个问题,但这是我对此的看法。

致以最诚挚的问候,希望对您有所帮助

您必须在 index.js 文件中启用 <StrictMode>

替换 <StrictMode><>

然后你会发现 render()componentDidMount 在你的 App 组件中只触发一次并且 componentWillUnmount 除非卸载 App 组件,否则不会触发

严格模式参考:https://github.com/facebook/react/issues/12856#issuecomment-613145789