Explain why React expects rendering to be a pure computation (UI = f(props, state, context)) and why side effects must be moved to effects/event handlers. Connect it to render vs commit, Concurrent Rendering, StrictMode double-invocation, memoization, and predictable reconciliation. Pure rendering improves predictability and testing, but side effects must live in effects/hooks. Test with StrictMode and rerenders.
Use this React interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.
Why are React components expected to be pure functions of props and state?Frontend interview answer
This React interview question tests whether you can explain should React components be pure functions of props and state, connect it to production trade-offs, and handle common follow-up questions.
- should React components be pure functions of props and state explanation without falling back to memorized docs wording
- State and Props reasoning, edge cases, and production failure modes
- How you would answer the most likely React interview follow-up
Core idea
React wants rendering to be a deterministic computation: given the same props + state (+ context), the component should return the same UI description. That purity lets React freely re-run renders, pause/abort work, and diff trees safely without causing “real-world” side effects.
Why purity matters | What it enables in React | What breaks if you add side effects in render |
|---|---|---|
Render can run multiple times | Retry / discard renders safely (especially in Concurrent Rendering) | Duplicate API calls, duplicate subscriptions, duplicated logs, inconsistent state |
Render can be paused / resumed / interleaved | Scheduling + prioritization without committing to the DOM | Effects happen at the wrong time, race conditions, tearing-like bugs |
React uses diffing + memoization | Predictable reconciliation, | Non-deterministic output makes “same inputs => same UI” false |
StrictMode intentionally stress-tests | Double-invocation in dev helps catch unsafe patterns | Impure render causes “works in prod, weird in dev” behavior |
Render vs side effects
Render phase should only compute the next UI tree. Side effects belong in event handlers (user actions) or effects (useEffect/useLayoutEffect) which run after React commits changes.
// ❌ Impure render: side effects inside render
let renders = 0;
function Profile({ user }) {
renders++; // side effect: mutating external state
// side effect: mutating props object
user.lastSeenAt = Date.now();
// side effect: starting async work during render
fetch('/api/track?u=' + user.id);
return <div>Renders: {renders} — {user.name}</div>;
}
Side effect in render | Why it’s bad | Where it should go instead |
|---|---|---|
Mutating props/state/external variables | Repeated renders produce cumulative mutations and hard-to-debug bugs | Compute derived values immutably; update state via setters |
Network calls / subscriptions / timers | Render may be retried/aborted → duplicated work and leaks | useEffect cleanup; subscribe/unsubscribe there |
Reading time/randomness (Date.now, Math.random) | Same inputs can yield different UI (non-deterministic) | Initialize once with lazy state init, or store in state |
DOM reads/writes | DOM may not match the tree until commit; causes layout issues | useLayoutEffect (reads/writes after commit) or refs |
// ✅ Pure render + side effects moved out
function Profile({ user }) {
// Pure: derived UI only
return <div>{user.name}</div>;
}
function ProfileWithTracking({ user }) {
React.useEffect(() => {
let cancelled = false;
(async () => {
try {
await fetch('/api/track?u=' + user.id);
} finally {
// optional: handle completion
}
})();
return () => {
cancelled = true; // example cleanup flag
};
}, [user.id]);
return <Profile user={user} />;
}
Rule of thumb
If running the component body twice would cause anything “real” to happen twice (API call, subscription, mutation, analytics), it’s not pure. Keep render as a calculation; do real work in effects and event handlers.
Practical scenario
A product card renders purely from props and local state, while data fetching happens in effects.
Common pitfalls
- Triggering side effects during render.
- Deriving state incorrectly from props.
- Relying on mutable props.
Pure renders are predictable but require disciplined effects. Test with StrictMode and snapshot behavior.
React expects components to be pure so it can re-run rendering freely (including retries/aborts), apply concurrent scheduling, and reconcile efficiently. Side effects in render break determinism and lead to duplicated work and inconsistent UI; move them to effects/event handlers where React guarantees timing relative to commits.
Use this as one explanation rep, then continue with the React interview questions cluster or a guided prep path.