Skip to content

React 18 strict mode docs are inconsistent about how unmount and remount actually works (and whether it's simulated) #6123

Closed
@AleksandrHovhannisyan

Description

@AleksandrHovhannisyan

Problem

The React v18.0 release article states the following about React 18's new strict mode behavior. Emphasis is my own:

To help surface these issues, React 18 introduces a new development-only check to Strict Mode. This new check will automatically unmount and remount every component, whenever a component mounts for the first time, restoring the previous state on the second mount.

However, in the following code demo, I'm able to use a ref to keep track of the number of times that useEffect runs, which I would not be able to do if the component were truly unmounting since refs are destroyed: https://codesandbox.io/s/run-mount-logic-only-once-zpywhc?file=/src/App.js.

import { useEffect, useRef } from "react";

export default function App() {
  const hasMounted = useRef(false);

  useEffect(() => {
    if (hasMounted.current === false) {
      hasMounted.current = true;
      console.count("mounted");
    }
  }, []);

  return <></>;
}

If the component truly unmounted and remounted and then restored state on the second mount, then the ref would not persist because 1) refs are not state (and hence not restored as described in the above quote), and 2) refs are normally destroyed on unmount. In that case, we would see the following logs:

mounted: 1
mounted: 2

However, what we actually see is:

mounted: 1

Which seems to suggest that React is not actually unmounting and remounting every component.

But later on, the same article clarifies that React simulates unmounting and remounting:

With Strict Mode in React 18, React will simulate unmounting and remounting the component in development mode:

Which makes a lot more sense: Effects are invoked twice to simulate an unmount and remount, but components are not truly unmounted. The React docs on Fixing bugs found by re-running Effects in development further clarify this:

When Strict Mode is on, React will also run one extra setup+cleanup cycle in development for every Effect. This may feel surprising, but it helps reveal subtle bugs that are hard to catch manually.

Suggestion:

There are two possibilities as far as I can tell:

  1. React does actually unmount and remount components, and it restores not only "state" but also anything within the scope of the component (e.g., refs).
  2. (More likely) React simulates remounting by simply invoking every effect twice.

Either way, I think it would be helpful to update all docs to be consistent. There's already quite a lot of misinformation out there on this subject and I've come across so many articles that claim React unmounts and remounts in strict mode on v18. For example, AG Grid's React 18 - Avoiding Use Effect Getting Called Twice article starts with the following:

React 18 introduced a huge breaking change, when in Strict Mode, all components mount and unmount, then mount again.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions