Search code examples
javascriptreactjsreconciliation

Nested React Component Re-rendering and React Reconcilliation


I'm struggling with understanding how reconciliation works when dealing with nested react components. Below is my code for 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"));

Below is index.html

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

The part that's confusing me is why all of the react instances keep on un-mounting and re-mounting every time I click the button. My understanding is that the "type" of the react instances aren't the same because we define the Todo component locally scoped inside of the TodoList component. Due to this, we are basically creating a new Todo component every-time during re-render. However, I feel that my explanation is a very high-level answer (Also, I'm not even sure if I'm correct) and I'm unsure of the lower-level implementation details on how the react reconciler manages distinctions between the "type" of react instances when we have nested vs un-nested components. (I'm using the term "nested" and "un-nested" as meaning defining a react component inside of the another react component like in the example I gave).


Solution

  • Todo component is unmounted because TodoList rerenders when state is changed. If you keep you Todo component outside of the TodoList component it will not unmount once state changes.