Back to React
React
medium
mid

What causes unnecessary re renders in React and how do you prevent them?

Common causes: parent re-render cascading, unstable prop references (new object/array/function each render), context value changing every render, hot state in Context, missing memoization for expensive children. Fixes: keep prop references stable (useMemo/useCallback when memo is downstream), split context, lift hot state to a selector-based store, React.memo for genuinely heavy children. Profile before applying.

4 min read·~8 min to think through

What "re-render" actually means

When a component renders, React calls its function and reconciles the returned JSX. Re-rendering itself is cheap; the downstream effects (large child trees, expensive computation, layout work) are what hurts.

Common causes

1. Parent re-render cascade

Any state change in a parent re-renders all children unless they're memoized. Usually fine — re-render of 10 components is trivial.

2. Unstable prop references

tsx
function Parent() {
  return <Child config={{ size: 4 }} onClick={() => doThing()} />;
}

Every render creates a new object + function. If Child is React.memo'd, the memo bails because props differ by reference. Fix:

tsx
const config = useMemo(() => ({ size: 4 }), []);
const onClick = useCallback(() => doThing(), []);

3. Context value changes every render

tsx
<Ctx.Provider value={{ user, setUser }}>   // new object each render

Every consumer re-renders. Fix:

tsx
const value = useMemo(() => ({ user, setUser }), [user]);

4. Hot state in Context

Context doesn't have selector subscriptions; any value change re-renders every consumer. Mouse position in Context = disaster. Move hot state to Zustand/Redux with selectors.

5. Inline definitions of memoized children

tsx
const X = memo(() => ...);   // good — defined outside

function Parent() {
  const X = memo(() => ...); // BAD — new component identity each render
}

6. useEffect setting state every render

tsx
useEffect(() => { setX(compute()); });   // no deps → fires every render → loop

7. Spread on every render

tsx
<Child {...props} extra={extra} />   // extra is fresh each render

When NOT to fix

If profiling doesn't show a hot path, memoizing adds cost (allocation, comparison) for no benefit. The reflex "useMemo everything" is an anti-pattern.

Profiling

React DevTools Profiler → "Why did this render?" shows whether it was parent re-render, state change, hook change, or props change. Highlight Updates renders to see what's flashing.

Fix patterns

SymptomFix
Big child re-rendering on parent stateReact.memo on child + stable prop refs
Context fan-outSplit context, or move hot state to selector store
Effect-driven re-render loopAdd deps; lift derivation out of state
Inline component defsMove outside render

Interview framing

"Re-renders aren't inherently bad — most are cheap. Real bottlenecks come from cascading into expensive subtrees: unstable prop references defeat memo, Context value changing every render fans out to every consumer, hot state in Context kills perf, inline component definitions break memo identity. The fix order: profile to find the actual hot path; stabilize prop references with useMemo/useCallback for the cases that matter; split context; move hot state to a selector-based store. Don't sprinkle memoization preemptively."

Follow-up questions

  • When does memoization hurt?
  • How would you debug a context fan-out?
  • Why does inline component definition break memo?

Common mistakes

  • useMemo/useCallback everywhere reflexively.
  • Context with hot state.
  • Effects with missing deps causing loops.

Performance considerations

  • Each memo costs allocation + comparison; only apply on confirmed hot paths.

Edge cases

  • Strict Mode double-render in dev.
  • Reconciliation across keys.
  • Memo + new object prop = always re-render.

Real-world examples

  • React docs profiling examples, Kent C. Dodds context blog post.

Senior engineer discussion

Seniors profile first; they recognize Context fan-out and split / move state accordingly.

Related questions