Effects You Do Not Need

Most effects in a struggling codebase synchronize with nothing external. They are ordinary logic pushed into a callback that runs one render too late, costing an extra render pass and a moment in which the screen shows inconsistent values.

Derived state belongs in the render, not in an effectJavaScript
// unnecessary: an extra render pass, and fullName is stale for one paint
const [fullName, setFullName] = useState('');
useEffect(() => { setFullName(first + ' ' + last); }, [first, last]);
// correct: one render, and the two can never disagree
const fullName = first + ' ' + last;
Common effects that should not be effects
An Effect that... What to do instead
Computes a value from props or state Calculate it during rendering
Runs because the user clicked or submitted Put the logic in the event handler
Caches an expensive calculation useMemo (useMemo)
Resets all state when a prop changes Pass that prop as key (Lifting State and Keys)
Updates state that another Effect then reads Compute both in one event handler
Notifies a parent after a state change Call the parent's callback in the handler
Subscribes to an external store useSyncExternalStore (useSyncExternalStore)

One question separates the two groups. If a user did something, the code belongs in an event handler; if the component being on screen is what requires the work, it belongs in an effect. "Send an analytics event when the Buy button is clicked" is a handler. "Keep the analytics session open while this page is visible" is an effect.