The pitfalls of useEffect cluster around the dependency array: a missing dependency reads a stale value, calling setState inside an Effect that also depends on that state causes an infinite loop, an object or function dependency is a fresh reference on every render, and forgetting the cleanup stacks duplicate listeners. Recognize these four classes of problem and most Effects become safe, because the Effect body finally does only what its name promises.
Group
Routing & State Mgmt
Kind
Pattern
ℹ️ Info The editor transpiles JSX to JavaScript and renders the real UI in a sandbox; components mount automatically — no manual render call needed.
📝 Syntax
useEffect(() => {
document.title = 'Current ' + count + ' times' // ① if you use count, declare it as a dependency
}, [count]) // ② dependency array: re-run only when it changes
useEffect(() => {
const id = setInterval(tick, 1000)
return () => clearInterval(id) // ③ clean up on unmount to avoid stacking
}, [])
Returns:No return value; this is a coding pattern rather than a callable API.
▶ Example
The example runs out of the box: it auto-renders when expanded, and edits take effect instantly.
Output:
The list updates as you type, and the Effect run counter only increments when query changes; below it spells out the consequences of the three big pitfalls: a missing dependency, an infinite loop and an object dependency.
⚠️ Warning Setting state inside an Effect while that same state is also a dependency is the number one source of infinite loops; first ask yourself "could this value be derived during render instead?".
💡 Tip Object, array and function dependencies are new references on every render - wrap them with useMemo/useCallback, or narrow the dependency down to a primitive.
ℹ️ Info In development React 18 StrictMode mounts, unmounts and mounts every Effect again on purpose, which surfaces missing cleanups for you.
A A setState inside the Effect changes a value that is also a dependency -> the state changes -> the Effect runs again -> it sets the state again, and so on. Fix it by removing that dependency, narrowing the dependency list, or deriving the value during render.
Q What exactly belongs in the dependency array?
A Every reactive value the Effect reads: props, state, and variables and functions defined inside the component. The exhaustive-deps rule of eslint reminds you about the ones you forget.
Q Does an empty array [] mean it runs only once?
A It means "independent of any value": it runs once on mount and the cleanup runs on unmount. If it reads state inside, it always sees the initial value - the closure trap.
Web-Tutorial Tech Team
A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.