The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →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
A React useEffect cleanup does not run on every render. React calls it before restarting the Effect after a committed render where a listed dependency changed, and when the component is removed. If the dependency array is empty, changing props or state will not restart the Effect; if a reactive value is missing from the array, React cannot use that change to trigger cleanup and setup.
When React runs an Effect cleanup
Think of cleanup as the undo step for an Effect’s setup, not as a general render callback. After a component commits, React runs the Effect’s setup. If a later committed render has a changed dependency, React runs the previous cleanup with the old values, then runs setup with the new values. When the component is removed, React runs cleanup for the last setup.
A rerender by itself is not enough. If every listed dependency compares equal to its previous value, React leaves that Effect in place. React compares dependencies using Object.is. React’s useEffect reference documents this lifecycle.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsCheck the dependency array first
An empty array means no prop- or state-driven restart
With useEffect(setup, []), the Effect does not rerun because a prop or state value changes. Its cleanup normally waits until unmount, aside from Strict Mode’s extra development-only check. An empty array is appropriate only when the Effect does not need to react to changing values from the component.
#1 Best Overall
If setup reads a prop, state value, or a variable or function declared in the component body, that value is reactive and generally belongs in the dependency list. Leaving it out can keep the Effect’s closure stale and prevent React from restarting the Effect when the value changes. Do not hide the mismatch by suppressing the dependency lint warning; change the code so the dependencies accurately describe what setup reads. See Removing Effect Dependencies.
No array means the Effect runs after every commit
If you omit the second argument entirely, React runs the Effect after every commit. When an array is present, inspect it for values whose identity changes each render, such as an object or function created in the component body. Such a change can trigger cleanup and setup even if the values look equivalent.
To investigate, log the dependency array on consecutive renders and compare corresponding entries with Object.is. Then restructure the Effect to avoid unnecessary dependencies where possible; memoization can help in appropriate cases, but React recommends fixing the underlying dependency structure first. React’s troubleshooting guidance describes this check.
Recommended Free Tools
Confirm the lifecycle event actually happened
Cleanup runs when a listed dependency changes or when the component unmounts. A component that is merely hidden, rerendered, or still present in the render tree has not necessarily unmounted. Check the parent’s conditional rendering and key changes, and confirm that the value you expect to trigger a restart is actually listed and changes between committed renders.
Rank #3
If cleanup is meant to happen immediately in response to a button click or other user action, put that action-specific work in the event handler instead of relying on an Effect. Effects are for synchronizing with external systems as the rendered state changes. If there is no external system to synchronize with, the Effect may be unnecessary. See You Might Not Need an Effect.
Make cleanup undo the setup
Cleanup should reverse the work performed by setup: disconnect what setup connected, unsubscribe from what it subscribed to, or clear the timer it started. React describes the principle this way: “The cleanup function should stop or undo whatever the setup function was doing.” The official Effect examples show this setup-and-cleanup pairing.
Rank #4
For example, if an Effect starts an interval, its cleanup should clear that interval. If the interval’s callback needs the latest state, a functional updater can avoid capturing that state and restarting the timer each time it changes:
useEffect(() => {
const id = setInterval(() => {
setCount(count => count + 1);
}, 1000);
return () => clearInterval(id);
}, []);
This pattern is suitable only if the Effect has no other reactive dependencies. The functional updater lets the callback compute from the pending state rather than reading a changing count value from the component closure. React’s interval example explains the dependency issue at Updating state based on previous state from an Effect.
Best Value
Interpret Strict Mode logs correctly
With Strict Mode enabled, React performs an extra setup, cleanup, and setup sequence in development before the normal setup. This is a stress test intended to expose cleanup that does not mirror setup; it is not the ordinary production schedule. Make setup and cleanup symmetrical so the extra cycle does not leave duplicate subscriptions, timers, or connections. React’s StrictMode reference explains the development-only behavior.
Do not switch to useLayoutEffect as a cleanup fix
useLayoutEffect has similar dependency-based cleanup behavior, but it runs work before the browser repaints and can block painting. It is intended for cases such as measuring layout before paint, not for making a missing or unchanged useEffect dependency trigger cleanup. Effects run only on the client. See React’s useLayoutEffect reference.
Quick Recap
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.

