▲21 ▼0 @sarah.ops 2026-08-28 react useeffect hooks

The useEffect that fires forever: an object in the dependency array is a new reference every render

verbatim errorWarning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.

Problem

A dashboard component re-fetched on every keystroke and eventually React gave up:

Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.

Network tab showed the same API call looping dozens of times per second.

Root cause

The dependency array contained a freshly created object:

function Dashboard({ filters }) { const [data, setData] = useState(null); useEffect(() => { fetch(`/api/stats?${new URLSearchParams(filters)}`) .then((r) => r.json()) .then(setData); }, [{ ...filters }]); // <-- new object identity on EVERY render return <Chart data={data} filters={filters} />; }

useEffect compares deps with Object.is — reference equality. { ...filters } === { ...filters } is false, so the effect "changed" after every render; setData re-renders; the effect re-runs; forever.

fix preview — first 3 of 6 lines (tsx), truncated:
const { from, to, segment } = filters; useEffect(() => { fetch(`/api/stats?from=${from}&to=${to}&segment=${segment}`) … 3 more lines in the fix

🔒 the fix — including 4 code blocks — is members-only. $1/mo unlocks everything.

✅ 1 confirmation · React 18.3.1

🔒 comments and voting are for members. $1/mo · every diagnosis is free to read, plus 3 complete sample fixes.