React Rendering Deep Dive: Render vs Commit (and How to Prove Rerenders)

A senior mental model of React rendering: render vs commit, reconciliation, why rerenders happen, and how to prove it using the React Profiler.

F

Frontend Interview Team

March 01, 2026

4 min read
React Rendering Deep Dive: Render vs Commit (and How to Prove Rerenders)

What you’ll learn

  • The difference between render and commit (and why it matters)
  • What reconciliation actually does (and what it doesn’t)
  • Why rerenders happen (even when the DOM doesn’t change)
  • How to prove a rerender with the React Profiler
  • The senior debugging loop for “this component rerenders too much”

The mental model: “React renders, then React commits”

React work (simplified) happens in two phases:

1) Render phase (pure computation)

React calls your components to compute what the UI should look like next.

  • It creates React elements
  • It compares new elements to previous ones (reconciliation / diffing)
  • It decides what needs to change

Important: During render, React is not touching the DOM yet.

2) Commit phase (effects + DOM mutations)

React applies changes:

  • Updates the DOM
  • Runs layout effects (useLayoutEffect)
  • Paint happens
  • Runs passive effects (useEffect)

If you remember one sentence:

A rerender means your component function ran again, not that the DOM necessarily changed.


What triggers a rerender?

A component rerenders when React decides it must re-run it to compute the next UI.

Common triggers:

  1. State update in the component (setState)
  2. Props change (parent rerender passes new props)
  3. Context value change used by the component
  4. Parent rerender (and the child isn’t memoized / bails out)

Subtle one: referential identity changes

Even if values look the same, passing a new reference forces React to treat props as “changed”.

function Parent() {
  const [count, setCount] = useState(0);
 
  // New object created every render
  const config = { theme: 'dark' };
 
  return <Child config={config} onClick={() => setCount((c) => c + 1)} />;
}

Every time Parent rerenders:

  • config is a new object reference
  • onClick is a new function reference
  • Child sees “new props”

Reconciliation: what React compares

React doesn’t diff “DOM HTML strings”. It diffs the tree of React elements.

Rules of thumb:

  • Same component type + same key → React tries to preserve state and update in place
  • Different component type or different key → React remounts (state resets)

How to prove rerenders (React Profiler)

Interviewers love when you say “I measured it.”

Steps (practical)

  1. Open React DevToolsProfiler tab
  2. Click Record
  3. Perform the interaction (type, click, filter)
  4. Stop recording
  5. Look for:
    • Which components rendered
    • How long each render took
    • “Why did this render?” (when available)

What you’re looking for

  • Components rendering on every keystroke that shouldn’t
  • A “hot” component with high self time
  • Repeated renders caused by new references

Senior debugging loop for rerenders

When someone says “this rerenders too much”, do this:

  1. Confirm with Profiler (don’t guess)
  2. Identify the trigger:
    • state? props? context? parent?
  3. Fix the trigger (in priority order):
    • move state down / colocate
    • stabilize references (useMemo, useCallback) only where needed
    • split components so expensive parts don’t rerender
    • memoize leaf components (React.memo) where it actually saves work
  4. Re-profile to confirm the win

Interview questions

Q1) What’s the difference between render and commit?

30-second answer: Render is React computing the next UI (pure), commit is applying changes to the DOM and running effects.

What they’re testing: Do you know where performance problems come from (CPU render cost vs commit/DOM cost)?

Follow-up: Where does useEffect run? Where does useLayoutEffect run?

Common wrong answer: “Render means it updates the DOM.”

Q2) Does rerender mean the DOM changed?

30-second answer: No. It means the component function ran again. React may bail out during commit if nothing changed.


Common mistakes

  • “Memo everything” (creates complexity and sometimes makes performance worse)
  • Optimizing before profiling
  • Large context providers causing wide rerenders

Quick recap

  • Rerender = component function executed
  • Commit = DOM mutations + effects
  • Prove with Profiler
  • Fix the trigger, not the symptom