AZ.dev

Why useEffect runs twice in development and how to write it so that's fine

| react: 18+

In development, Strict Mode mounts each component, unmounts it, and mounts it again, so an effect runs, cleans up, and runs once more. The fix is an effect whose cleanup fully undoes its setup.

useEffect(() => {
  const id = setInterval(tick, 1000);
  return () => clearInterval(id);
}, []);

With that cleanup the double run leaves one interval. Without it, two tick side by side, and the “bug” is the missing cleanup, which would also have bitten on any real remount.

The patterns that break

What this is not

It isn’t a render loop, and it isn’t a dependency problem. Production builds don’t double-invoke; React.StrictMode only does this in development, and only for effects, reducers and render functions, to expose exactly the missing cleanups above.

Gotchas

useEffect strict-mode cleanup subscriptions development

This entry is one card on a printable cheat sheet:

React Essentials Cheat Sheet

Was this helpful?

Related Entries

Update state from its previous value without losing updatesReset a component's state when the thing it shows changes