Why React Separates Render and Commit (And Why It Confused Me at First)
React doesnât update the UI immediately when state changes. It first re-runs your components to calculate what the UI should look like (render phase), and only after that applies the changes and runs effects (commit phase). This is why components must stay pure and why useEffect runs after the UI updates.
At some point, React starts behaving in ways that donât feel intuitive.
You log something, and it runs multiple times.
You update state, but nothing changes immediately.
You use useEffect, but it runs after everything.
It creates a strange feeling:
âWhen is React actually doing things?â
The Part That Feels Off
At first, itâs easy to think React works like this:
state changes â UI updates â effects run
A simple, linear flow.
But thatâs not how React actually works.
Instead, React splits everything into two separate phases:
render and commit
Render Phase Is Just Thinking
The render phase is where React figures things out.
When state changes, React:
- calls your component again
- runs your hooks
- calculates what the UI should look like
But hereâs the important part:
nothing is applied yet
No DOM updates.
No effects.
No visible changes.
Itâs just computation.
Why Render Must Be Pure
React treats render like a draft.
And drafts can be:
- re-written
- paused
- thrown away
Because of that, render must follow one rule:
it must be pure and repeatable
Thatâs why:
- no API calls
- no DOM manipulation
- no side effects
Because React might run it multiple times before deciding anything.
Commit Phase Is Where Things Become Real
Once React finishes calculating, it moves to the commit phase.
This is where React:
- updates the DOM
- shows changes on screen
- runs
useEffect - runs cleanup
This phase is different:
it cannot be interrupted
What happens here is final and visible.
Putting Them Together
When you call:
setCount(count + 1)React doesnât immediately update the UI.
Instead:
1. Render phase
- re-run component
- compute new UI
- compare with previous result
2. Commit phase
- update DOM
- run effects
- reflect changes on screen
Why This Separation Exists
This design isnât accidental.
It allows React to:
- pause rendering if itâs expensive
- restart if new updates come in
- prioritize important updates (like user input)
In short:
React wants the freedom to think before acting
Why useEffect Feels âLateâ
A common confusion:
âWhy does useEffect run after everything?âBecause it belongs to the commit phase.
So React:
- calculates UI
- updates the screen
- then runs effects
Not before.
The Subtle Shift
At first, React feels like:
âstate changes â UI updatesâ
But internally, itâs closer to:
âstate changes â recompute everything â then apply onceâ
The Mental Model That Helps
Instead of thinking in steps, think in versions.
Each render creates:
a new version of your UI
React then compares:
- previous version
- next version
And only after that, it commits the difference.
Why This Connects to Everything Else
Once this clicks, a lot of things start making sense:
- why components must be pure
- why
useMemoexists - why
useEffectruns after render - why React can re-render without visible changes
Final Takeaway
Render is where React thinks.
Commit is where React acts.
And the gap between those two is where most confusion comes from.
Because what feels like âone stepâ is actually two very different phases happening behind the scenes.