'CRA unmounts a component and mounts it back on every save

Consider the code snippet below:

import { useEffect } from "react";

export const Hello = () => {
  useEffect(() => {
    console.log("Mounted");
    return () => {
      console.log("Unmounted");
    };
  }, []);

  return <h1>Hello</h1>;
};

I'm observing that every time I make some changes and save, I get the Unmounted and Mounted log printed, which means that the component is getting unmounted and then mounted back.

This is not something critical, but in my project I'm working with Iframes and on unmount I run some code that I don't want to run unnecessarily.

Was this the case from the start, did something change?



Solution 1:[1]

This wasn't always the case, CRA earlier used "React Hot Loader" but with version 4 it upgraded to "React Fast Refresh".

Fast Refresh introduces the concept of reusable state. With fast refresh every time you save a file, your effects would re-run but the state of the components are preserved.

Note: You should ensure that your components are resilient to being "mounted" and "unmounted" more than once and React 18's strict mode even ensures this resilience by "unmounting" & "re-mounting" newly mounted components, read more here.

Solution 2:[2]

When using hot module reloading, changing something inside a functional component and saving will not result in the component being unmounted and mounted again but all effects re-run.

Source: Comment from Dan Abramov, author of React Hot Loader

This is the case for functional components in general. As stated in the React documentation on useEffect:

When exactly does React clean up an effect? React performs the cleanup when the component unmounts. However, as we learned earlier, effects run for every render and not just once. This is why React also cleans up effects from the previous render before running the effects next time.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2