Why React Cares So Much About âPureâ Rendering
React keeps rendering pure, meaning components only describe UI without causing side effects. This allows React to safely re-render or discard work without bugs. Side effects are handled separately using useEffect to keep everything predictable.
Thereâs a moment when learning React where something starts to feel⌠restrictive.
You try to fetch data, set up something, or run a piece of logicâand suddenly youâre told:
âDonât do that here. Use useEffect.âAt first, it feels like React is just being annoying.
Why canât we just run things when the component is about to mount? Why must everything wait until after render?
The answer sits in one idea that React takes very seriously:
rendering should be pure.
What âPureâ Actually Means
When React calls your component, it expects one thing:
function Component() {
return <div>Hello</div>
}Given the same inputs (props, state), it should always return the same output.
No surprises. No hidden behavior.
Thatâs what âpureâ means here.
Where It Starts to Break
Now imagine doing this inside your component:
function Component() {
fetch("/api/data")
return <div>Hello</div>
}It might work⌠but something feels off.
Because now your render is doing more than just describing UI.
Itâs:
- triggering a network request
- causing side effects
- interacting with something outside React
Thatâs no longer pure.
Why React Doesnât Allow This
The problem isnât just about âclean codeâ.
Itâs about how React actually runs your component.
React doesnât guarantee that a render will always be used.
It can:
- render a component
- pause it
- throw it away
- render again
This happens in modern React with things like concurrent rendering.
Now Imagine This Scenario
function Component() {
fetch("/api/data")
return <div>Hello</div>
}React:
- renders â API call happens
- discards render
- renders again â API call happens again
You now have:
- duplicate requests
- inconsistent behavior
- bugs that are hard to trace
This Is Why Purity Matters
By keeping render pure, React ensures:
- no side effects during render
- no accidental duplication
- predictable behavior
Rendering becomes something React can safely run multiple times.
So Where Do Side Effects Go?
Thatâs where useEffect comes in.
useEffect(() => {
fetch("/api/data")
}, [])Now the flow is different:
- React renders
- DOM updates
- Effect runs
This guarantees:
- the component is actually mounted
- the work is not wasted
- the side effect runs at the right time
The Trade-off
You lose something:
- you canât run logic âbefore renderâ
But you gain something more important:
- consistency
- safety
- control in a more predictable way
A Better Way to Think About It
Instead of asking:
âWhen should this run in the lifecycle?â
Think:
âIs this part of rendering, or is this a side effect?â
If it affects the outside world:
- API calls
- timers
- event listeners
- third-party libraries
It doesnât belong in render.
Why This Design Feels Different
If youâve used frameworks like Vue, this can feel limiting.
Youâre used to hooks like:
beforeMountmounted
Where you can control exactly when things happen.
React takes a different approach.
It removes that control in exchange for stronger guarantees.
The Core Idea to Keep
Rendering is just a description.
It should not:
- change anything
- trigger anything
- depend on external effects
It should only answer:
âWhat should the UI look like right now?â
Final Takeaway
The restriction isnât there to make things harder.
Itâs there to make React reliable.
Once you accept that rendering is pure, everything else starts to fall into place:
- why
useEffectexists - why thereâs no
beforeMounted - why React can re-render freely
And most importantly:
why your UI stays predictable even as your app grows