4

When setting state after a component was unmounted, React should log the following error:

Warning: Can't perform a React state update on an unmounted component.
This is a no-op, but it indicates a memory leak in your application.
To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

However, If I'm returning an empty function as the cleanup function it would not log the error.

the code:

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

function Comp() {
  const [state, setState] = useState("nothing");

  useEffect(() => {
    setState("loading");

    sleep(1000).then(() => {
      console.log("setting state");
      setState("finished");
    });

    // When the below return exists it does not log the error
    return () => {};
  }, []);

  return <span>{state}</span>;
}

export default function App() {
  const [show, setShow] = useState(true);

  useEffect(() => {
    sleep(500).then(() => setShow(false));
  }, []);

  return (
    <div className="App">
      <h1>
        <button onClick={() => setShow((v) => !v)}>Show</button>
        {show && <Comp />}
      </h1>
    </div>
  );
}

Sandbox link

Raz Luvaton
  • 3,166
  • 4
  • 21
  • 36
  • The issue here is that you are using an async function inside of the useEffect hook. If the promise isn't resolved before the component unmounts you will get this error. The cleanup function is similar to the old 'componentWillUnmount' function which will execute only after the logic inside of your hook (componentDidMount) is executed. I know the docs can get confusing with this so here is a good article on this. Hope it helps! https://blog.logrocket.com/understanding-react-useeffect-cleanup-function/ – Dylan Prem Mar 10 '22 at 14:42
  • Does this answer your question? [React useEffect causing: Can't perform a React state update on an unmounted component](https://stackoverflow.com/questions/54954385/react-useeffect-causing-cant-perform-a-react-state-update-on-an-unmounted-comp) – Dylan Prem Mar 10 '22 at 14:51
  • Thank you but this is actually the opposite as I expect it to log but it won't – Raz Luvaton Mar 10 '22 at 14:57
  • 1
    Good question! Worth mentioning: It _does_ warn for (a.) class components, and (b.) components one level deeper, e.g. `{ show &&
    }` or `{ show && }` with `function CompContainer() { return }`
    – kca Mar 11 '22 at 21:45
  • 1
    I think I might have found the condition that prevents the warning for non-nested functional components: [PassiveUnmountPendingDev](https://github.com/facebook/react/blob/v17.0.2/packages/react-reconciler/src/ReactFiberWorkLoop.old.js#L3066). – kca Mar 11 '22 at 22:48
  • 1
    Apparently that warning will be removed soon: [Pullrequest #22114](https://github.com/facebook/react/pull/22114), [commit 7ed0706d](https://github.com/facebook/react/commit/7ed0706d) is already merged. (but not yet in current verion v17.0.2) – kca Mar 11 '22 at 22:51

0 Answers0