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.
Frontend Interview Team
March 01, 2026
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:
- State update in the component (
setState) - Props change (parent rerender passes new props)
- Context value change used by the component
- 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:
configis a new object referenceonClickis a new function referenceChildsees “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)
- Open React DevTools → Profiler tab
- Click Record
- Perform the interaction (type, click, filter)
- Stop recording
- 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:
- Confirm with Profiler (don’t guess)
- Identify the trigger:
- state? props? context? parent?
- 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
- 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