Note The effect runs after the component renders. The dependency array controls when it re-runs. Omit the array: runs after every render. Empty array []: runs once on mount. With values: runs when any dependency changes.
useEffectside effectafter renderlifecyclecomponent mount
Dependency Array
syntax
useEffect(effectFn, [dep1, dep2]);
// Empty array: mount only
useEffect(effectFn, []);
// No array: every render
useEffect(effectFn);
Note React uses Object.is to compare dependencies. Objects and arrays create new references each render, so they will always trigger the effect. Extract primitive values or memoize objects before listing them as dependencies.
Note The cleanup function runs before the effect re-executes (when dependencies change) and when the component unmounts. This prevents memory leaks from subscriptions, timers, and open connections.
Note The ignore flag prevents setting state on an unmounted component or after a stale request. In React 19, consider using the use() hook with Suspense for data fetching instead of this pattern.
Note Always remove event listeners in the cleanup to avoid duplicate handlers and memory leaks. The handler reference must be the same function for addEventListener and removeEventListener.
Note Always clear intervals and timeouts in cleanup. Use the updater form (prev => prev + 1) inside intervals to avoid stale closure issues with the state value.
Note Overusing useEffect is one of the most common React mistakes. If you can calculate something from existing props or state, do it during render. If something should happen in response to a user action, put it in the event handler.
avoid useEffectderived stateunnecessary effectwhen not to use effectcompute during render