Recommended Free Tools
A React useEffect cleanup does not run on every render. React runs it before restarting that Effect after a commit where a listed dependency changed, and when the component unmounts. If the dependency array is empty—or none of its values changed—ordinary rerenders will not trigger cleanup.
When React runs an Effect cleanup
Think of cleanup as the teardown step for an Effect’s synchronization with an external system, not as a general render callback. After a component commits, React runs the Effect’s setup. If a later committed render changes one or more dependencies, 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.
As an Amazon Associate I earn from qualifying purchases.
React compares each dependency with its previous value using Object.is. A rerender by itself is not enough: if all listed dependencies compare equal, React leaves the Effect alone. See the React useEffect reference for the lifecycle details.
Check which dependency pattern you have
Empty array: []
An empty array means the Effect has no reactive dependencies to track. Prop or state changes do not restart it, so its cleanup ordinarily waits until unmount. This is appropriate only when the Effect does not need to respond to values that change over time. If setup reads a changing prop or state value, leaving it out can leave the Effect using an outdated value. The React guide to the lifecycle of reactive Effects explains how to identify reactive values.
#1 Best Overall
Dependency omitted entirely
With useEffect(setup), React runs the Effect after every commit. It runs cleanup before the next setup, so this pattern should not make cleanup wait for unmount. If your cleanup appears absent, verify that the Effect actually committed and inspect the component’s mount and render behavior.
One or more dependencies are missing
Every reactive value read by setup—including props, state, and functions or variables declared in the component body—belongs in the dependency list. When a missing value changes, React cannot use it to restart the Effect, and the existing setup may keep a stale closure. Make the dependency list match the code; do not silence the warning as a substitute. See Removing Effect Dependencies for ways to restructure an Effect when the list is inconvenient.
All listed dependencies are unchanged
If the component remains mounted and each listed dependency compares equal to its previous value, React has no reason to clean up and restart that Effect. If cleanup is meant to happen directly in response to a click or another user action, put that action-specific behavior in the event handler rather than relying on an Effect to infer it.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Debug the lifecycle and dependency values
- Inspect the dependency array. Confirm whether it is omitted, empty, or complete for the values setup reads.
- Confirm the trigger. A cleanup runs on a dependency change or on unmount—not merely because the component rendered again. Check the conditions that show or remove the component.
- Log dependencies across renders. Compare corresponding values with
Object.is. An object or function created anew during rendering can change identity even if its contents appear equivalent, causing cleanup and setup to repeat. The React troubleshooting guidance describes this check. - Make cleanup reverse setup. Disconnect what setup connected, clear the interval it started, or undo the subscription it established. React’s synchronizing with Effects guide discusses matching setup with cleanup.
When dependencies make an interval restart
A common interval bug occurs when setup reads count and lists it as a dependency. Each count change then causes React to clean up the old interval and start another one. If the interval only needs to increment the latest state, use a functional updater so its callback does not capture count:
Rank #3
useEffect(() => {
const id = setInterval(() => {
setCount(count => count + 1);
}, 1000);
return () => clearInterval(id);
}, []);
This empty array is suitable only if the Effect has no other reactive values that need to be tracked. The pattern follows React’s interval example.
Why Strict Mode can show an extra cleanup
In development, when Strict Mode is enabled, React performs an additional setup-and-cleanup cycle before the Effect’s real setup. This is a check that cleanup mirrors setup; it is not the normal production schedule. Make setup and cleanup symmetrical so the extra cycle does not create duplicate subscriptions, timers, or connections. See React StrictMode.
Rank #4
Should you switch to useLayoutEffect?
Usually, no. Effects run only on the client, and useLayoutEffect has similar dependency and cleanup behavior while blocking repaint. Use it when work must happen before the browser paints, such as measuring layout—not as a workaround for an incomplete dependency array. See the useLayoutEffect reference.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
When an Effect may not be the right tool
Effects are for synchronizing with external systems. If an Effect does not interact with one, consider whether the logic belongs in rendering or in an event handler instead. Moving interaction-specific work to the handler can make its timing explicit and avoid expecting cleanup to respond to an action it does not track. React’s You Might Not Need an Effect guide covers these cases.
Quick Recap
Best Value
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.




