嵌套的 React 组件重新渲染和 React 协调

Nested React Component Re-rendering and React Reconcilliation

在处理嵌套的 React 组件时,我很难理解协调的工作原理。下面是我的 index.js

代码
import React from "react";
import { render } from "react-dom";
import { useState, useEffect } from "react";

const TodoList = ({ todos }) => {
  useEffect(() => {
    console.log("mounted List")

    return () => {
      console.log("unmounted List")
    }
  }, [])

  const Todo = ({ txt }) => {
    useEffect(() => {
      console.log("mounted Todo")

      return () => {
        console.log("unmounted Todo")
      }
    }, [])

    return (
      <li>
        {txt}
      </li>
    );
  };
  return todos.map(todo => <Todo {...todo} />);
};

const App = () => {
  const [todos, setIt] = useState([{ txt: "foo" }, { txt: "bar" }, { txt: "baz" }])
  return (
    <>
      <button onClick={() => setIt(todos.concat({ txt: 'new' }))}>Click</button>
      <TodoList todos={todos} />
    </>)
}

render(<App />, document.getElementById("root"));

下面是index.html

<div id="root"></div>

让我感到困惑的部分是为什么每次单击按钮时所有反应实例都会继续卸载和重新安装。我的理解是反应实例的“类型”不一样,因为我们在 TodoList 组件内部定义了 Todo 组件 locally scoped。因此,我们基本上每次在重新渲染期间都会创建一个新的 Todo 组件。但是,我觉得我的解释是一个非常高层次的答案(另外,我什至不确定我是否正确)并且我不确定关于反应协调器如何管理两者之间区别的较低层次的实现细节当我们有嵌套组件和未嵌套组件时,反应实例的“类型”。 (我使用术语“嵌套”和“非嵌套”来表示在我给出的示例中定义另一个反应组件内部的反应组件)。

Todo 组件已卸载,因为 TodoList 在状态更改时重新呈现。 如果您将 Todo 组件放在 TodoList 组件之外,一旦状态发生变化,它就不会卸载。