Renders are snapshots
Each render sees its own props and state; updates schedule new renders, are batched, and effects run after paint, children first. Keys decide identity. Reason from those rules.
- StateSnapshots, updater functions and batching.
- EffectsOrder, StrictMode and dependencies.
- IdentityKeys and stale closures.
React output questions test your mental model of rendering. Each one asks “what renders, how many times, with which value?” — and the explanations below give you the rule to reason through any variation.
1. What does the counter show after one click?
1. All three updates read the same count from this render (0) and set it to 1. Use the updater form setCount(c => c + 1) to get 3.
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => { setCount(count + 1); setCount(count + 1); setCount(count + 1); }}>{count}</button>;
}2. What is logged when the button is clicked? (state is a snapshot)
0. count is a constant for this render; setting state schedules a new render but does not change the variable in the current one.
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
console.log(count); // 0
}3. Why does this interval always show 1? (stale closure)
The effect runs once with an empty dependency array, so its callback captures count = 0 forever and keeps setting 1. Use the updater function, or include the dependency.
useEffect(() => {
const id = setInterval(() => setCount(count + 1), 1000); // stale count
return () => clearInterval(id);
}, []);
// fix
useEffect(() => {
const id = setInterval(() => setCount(c => c + 1), 1000);
return () => clearInterval(id);
}, []);4. How many times does the component render after this click?
Once. React 18+ batches state updates inside event handlers, timeouts and promises into a single render.
function handleClick() {
setName('Asha');
setAge(22);
setCity('Pune'); // one re-render, not three
}5. In what order are these logged on mount?
render, child effect, parent effect (once StrictMode is off). React renders parent then child, but runs effects bottom-up: children first, then parents.
function Child() {
useEffect(() => console.log('child effect'));
return null;
}
function Parent() {
console.log('render');
useEffect(() => console.log('parent effect'));
return <Child />;
}6. Why is my effect running twice in development?
React StrictMode intentionally mounts, unmounts and remounts components in development to expose missing cleanup. It does not happen in production. Fix the effect's cleanup rather than removing StrictMode.
7. Why does this effect run on every render?
The dependency is an object created during render, so it is a new reference each time and the comparison always fails. Move it inside the effect, memoise it, or depend on primitive values.
const options = { city, page }; // new object every render
useEffect(() => { fetchJobs(options); }, [options]); // runs every render
useEffect(() => { fetchJobs({ city, page }); }, [city, page]); // fix8. Why does the wrong input keep its text after deleting an item?
The list uses the array index as key. After deleting item 0, item 1 gets key 0, so React reuses the first input's DOM and state for a different item. Use stable ids.
{items.map((item, index) => <TodoRow key={index} item={item} />)} // buggy after delete
{items.map(item => <TodoRow key={item.id} item={item} />)} // correctRemember
Key points
- setX(prev => …)
When the new value depends on the old.
- Updates are batched
One render for many setters.
- Effects run child first
After the commit.
- Stable keys keep state
Never the index for editable lists.
Interview drill
Follow-up questions
What the interviewer asks after your first answer. Turn on practice mode, answer each one aloud, then reveal.
-
1 Does setState with the same value re-render? Intermediate
React bails out if the new value is identical (Object.is), though it may render the component once more before bailing out of its children.
-
2 Why does a child re-render when its props did not change? Basic
Parents re-render children by default; wrap the child in React.memo (with stable props) to skip it.
-
3 What runs first, useLayoutEffect or useEffect? Intermediate
useLayoutEffect, synchronously after DOM updates and before paint; useEffect runs after paint.
-
4 Can you call a hook inside a condition if the condition never changes? Intermediate
Still breaks the rules of hooks and lint will flag it; restructure so hooks are always called in the same order.
-
5 What happens if you update state during render? Advanced
React re-runs the render immediately; doing it unconditionally causes an infinite loop. Only guarded updates (deriving state from props) are allowed.
-
6 Why does useRef not trigger a re-render? Basic
Changing ref.current mutates an object React does not track; use state if the UI must update.