useEffect runs after the first render and after every update. But plenty of effects only make sense on changes — refetching when a filter changes, saving a draft when it edits, reacting to a prop that moved — and firing them on mount duplicates work you already did during initial render, or worse, triggers a spurious network call or toast the instant the component appears. useUpdateEffect is useEffect with the mount run skipped: it fires only on subsequent dependency changes.
Implement useUpdateEffect(effect, deps). Same signature as useEffect. Skip the very first run; on every later run caused by a dependency change, invoke effect and honor any cleanup function it returns.
function useUpdateEffect(effect, deps) {
// like useEffect, but does NOT run on mount
}
useUpdateEffect(() => {
refetch(query); // runs when `query` changes, NOT on mount
}, [query]);
useUpdateEffect(() => {
const id = setInterval(tick, delay);
return () => clearInterval(id); // cleanup honored, just like useEffect
}, [delay]);
effect.useEffect for all subsequent dependency changes.effect returns so React can clean up before the next run and on unmount.