I’ve started reviewing PRs with a single rule for useEffect: if I can’t explain in one sentence why this could not have been derived from props, I’m going to ask you to remove it.
It’s been a quietly transformative rule.
What useEffect is for
Effects exist to synchronise React’s render output with something outside of React: the DOM (focus management, scroll position), the network (subscriptions, polling), the platform (timers, observers). If the thing you’re synchronising lives inside React’s own world, state, props, context, then the synchronisation should happen during render, not after it.
What it’s not for
The list of things useEffect is not for, but is constantly used for:
- Computing derived values from props. Just compute them in the render body.
- Resetting local state when a prop changes. Use a
keyprop on the parent. - Caching expensive calculations. Use
useMemo. Or don’t, most calculations aren’t expensive. - Calling a function “when the component renders”. A render is the function being called. You’re asking for a callback after the call you just made.
- Keeping two pieces of state in sync. One of them is redundant. Delete it.
Why it matters
Each useEffect has a hidden cost: it adds a moment in time after render where the world is almost consistent but not quite. You set state in an effect; the user sees the wrong thing for a frame; the effect fires; the component re-renders; now it’s right.
Multiply by ten effects in a deep tree and you have a UI that flickers in subtle, uncatchable ways. The bug report says “sometimes the X is wrong for a moment”. The cause is six useEffect calls deep in a component tree, each waiting one render cycle to update the next.
The fix is usually deletion
The most common fix when I find a misused useEffect is to delete it entirely and move the logic into the render body. That feels wrong, surely something has to happen “after”?, but it’s almost always right. The render body runs every render. State changes already trigger re-renders. There’s no missing step.
A fire alarm should ring when there’s a fire. Most of what we use it for is a kettle boiling.