What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

If a React Effect appears to run twice when a component mounts, check whether <StrictMode> is enabled. In development, React deliberately runs an extra Effect setup-and-cleanup cycle to test whether the Effect cleans up after itself. The right fix is usually to make setup and cleanup work as a pair—not to hide the second setup with a ref.

Why does my Effect run twice when the component mounts?

With Strict Mode enabled, React performs an additional development-only cycle before the first real Effect setup: it runs setup, runs the returned cleanup, then runs setup again. That check helps reveal Effects that leave behind subscriptions, connections, or other work when they should stop. React describes the expected behavior as one the user cannot distinguish from a single setup in production. See the React useEffect reference and StrictMode reference.

This extra cycle is a development check; by itself, it does not mean the initial Effect will run twice in production. The behavior was introduced as a Strict Mode development check in React 18, but current React documentation describes the behavior and its scope. Strict Mode also checks other patterns, including rendering and callback refs.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

There is a scope caveat: if Strict Mode is enabled only around a subtree rather than at the root, React does not perform the initial extra Effect cycle for that subtree when it would cause child Effects to run without corresponding parent Effects. That parent-child sequence cannot happen in production, so React avoids simulating it.

What an Effect and its cleanup should do

useEffect synchronizes a component with something outside React, such as a service connection, subscription, or browser API. The setup starts or establishes that synchronization. Its cleanup should stop or undo the work created by that setup.

For example, create a connection inside the Effect and return a cleanup that disconnects that same connection:

useEffect(() => {
  const connection = createConnection(serverUrl, roomId);
  connection.connect();

  return () => {
    connection.disconnect();
  };
}, [serverUrl, roomId]);

During the development check, this Effect connects, disconnects, then connects again. The result is one live connection, not two. React also calls cleanup before setting up the Effect again when its dependencies change, and when the component is removed. A dialog opened through an API that cannot safely be opened twice in a row needs corresponding cleanup that closes it before the next setup.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The practical test is whether setup → cleanup → setup leaves the same working state as one setup. React’s guidance in Synchronizing with Effects explains why cleanup is part of the Effect rather than an optional response to a development quirk.

Why a ref guard is the wrong fix

A guard such as useRef(false) that skips the second setup can make the development check disappear, but it does not repair incomplete cleanup. A subscription or connection from the first setup may remain active, and later remounts or dependency changes can still expose the lifecycle bug. React specifically warns against using a ref to prevent an Effect from running more than once as a way to avoid the development check.

Instead, make the Effect safe to start, stop, and start again. If the Effect cannot undo what it does, reconsider whether that work belongs in an Effect or whether the external operation offers a way to cancel, close, or otherwise reverse it.

Tell the Strict Mode check apart from other reruns

Not every repeated Effect is the initial Strict Mode check. Effects also rerun after commits when dependencies change. React compares dependency values with Object.is; an Effect without a dependency list runs after every commit. Objects and functions created during rendering can also have a new identity on each render, making them appear changed and triggering reruns.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Initial Strict Mode check: setup → cleanup → setup in development when Strict Mode applies.
  • Dependency change: cleanup for the previous setup, then setup with the new dependency values.
  • No dependency list: the Effect runs after every commit.
  • Render loop: the Effect updates state, causing another render and potentially another Effect run. Check whether a dependency changes as a result.

Include the reactive values used by the Effect and simplify unnecessary object or function dependencies rather than removing dependencies just to silence reruns. The useEffect reference documents dependency comparison and the mounting troubleshooting case.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Put user-triggered actions in event handlers

An Effect responds to rendering and keeps an external system synchronized with the component. It is not the right place for a one-off action that should occur only after a particular user intention. For example, a purchase should be initiated by the purchase button’s event handler, not by an Effect that happens to run after rendering. Otherwise, rendering or remounting can trigger an action the user did not just request. For one-time application initialization that is not synchronization with an external system, React’s guidance is to put it outside the component. See Synchronizing with Effects.

Why useLayoutEffect is not a workaround

useLayoutEffect is for visual work that must happen before the browser paints, such as measuring a tooltip and positioning it to avoid a visible jump. It blocks repainting while it runs, so it is not a general substitute for useEffect and does not solve an Effect that lacks correct cleanup. Use it only when the timing requirement is genuinely visual and before-paint. See React’s useLayoutEffect reference.

Should you disable Strict Mode?

Strict Mode is recommended for React applications, particularly new ones, because its development checks can expose lifecycle errors before they cause confusing behavior elsewhere. If the extra cycle reveals duplicate external work, repair the Effect’s cleanup or move interaction-specific work into the relevant event handler. Disabling the check or masking it with a ref avoids the signal rather than fixing the underlying behavior.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.