Topic 26.2
Core React Interview Questions
In one line
The questions almost every React interview asks (virtual DOM, keys, controlled vs uncontrolled inputs, state vs props, the component lifecycle in hooks, StrictMode and more) with model answers and live demos that prove the tricky claims.
Think of it like this
A driving test. The examiner doesn't ask you to recite the engine manual; they ask short questions ("what does this sign mean?") and then watch you drive. React interviews work the same way: a short question, a clear answer in your own words, and then a small demo or follow-up that shows you really understand it. This topic gives you both: model answers, and live code you can run while you explain.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Virtual DOM
- The tree of element objects your components return. React compares it with the last one to find what to change.
- Reconciliation
- React comparing the new elements with what it has (fibers) to decide what to keep, update, add or remove.
- Key
- A stable id for an item among its siblings, so React matches it to the same state and DOM node across renders.
- Controlled input
- An input whose value comes from React state and changes only through
onChange. - Uncontrolled input
- An input that keeps its own value in the DOM; React only gives it a
defaultValue. - Props
- Read-only inputs a parent passes to a child.
- State
- A component's own memory; changing it with the setter schedules a re-render.
- Batching
- React grouping several state updates from the same event into one render.
- StrictMode
- A development-only wrapper that double-runs renders and effects to expose bugs.
Step by step
01Answer in three beats: definition, mechanism, consequence
Practise every question below out loud with this shape. Keep the definition to one sentence; spend most of the answer on the mechanism; end with a real bug or rule it explains. If you can, offer to show it: "I can sketch a two-line demo".
02Virtual DOM and reconciliation
A render creates elements; React diffs them against the current fibers; the commit writes only the changes. Mention the two rules (type and key) and that the cost is O(n), not a general tree diff.
03Keys: prove it with a list that gets a new first item
The live demo types a note next to Asha in two lists, then adds Meera at the top. With index keys, the note stays at position 0 and now sits next to Meera. With id keys, the note moves with Asha.
04State is a snapshot, setters are batched
Inside one render count is a constant (Topic 4.4). Calling setCount(count + 1) three times queues "set to 1" three times. Updater functions queue "add one" three times. React batches all of them into one render (Topic 4.5).
setCount(count + 1); // count is 0 in this render: "set to 1"
setCount(count + 1); // "set to 1" again
setCount((c) => c + 1); // "take the queued value and add 1"05Lifecycle questions: answer in effects
When asked "how do you do componentDidMount in hooks?", give the mapping and then the better framing: effects synchronise a component with something outside React; they run after commit and clean up before re-running and on unmount.
Try it yourself
- 1
Turn the index list into an id list
In the keys demo, predict what happens if Meera is added at the bottom instead (
[...people, { id: 3, name: "Meera" }]). Run it. Both lists now look right, because positions 0 and 1 didn't change. That's why index keys seem fine until someone inserts at the top or sorts. - 2
Mix the two setter styles
In the batching demo, change the right button to
setCount((c) => c + 1); setCount(count + 10); setCount((c) => c * 2);. Predict the new count after one click, starting from 4. (5, then 14, then 28: a plain value replaces whatever was queued before it.) - 3
Fix the mirrored prop two ways
First remove the state and render
{name}directly. Then try the other fix: keep the state but render<Greeting key={name} name={name} />. Both showRaviafter the click; the key version also resets any other state insideGreeting.
Code & diagrams
The typed text lives in the DOM input, which belongs to a fiber matched by key. With index keys, key 0 is now Meera's row, so she inherits Asha's input. With id keys, React moves Asha's row and inserts a new one for Meera.
Preview
Console
Nothing logged yet.Expected console output
key = index: Meera=likes tea, Asha=(empty), Ravi=(empty)
key = id: Meera=(empty), Asha=likes tea, Ravi=(empty)Three setter calls produce one render either way (batching). The first button adds 1 because each call says "set to 0 + 1"; the second adds 3 because each updater receives the result of the previous one.
Preview
Console
Nothing logged yet.Expected console output
render, count = 0
inside the handler, count is still 0
render, count = 1
render, count = 4This example uses StrictMode on purpose. In development React renders twice and runs setup → cleanup → setup, so an effect without cleanup would leave two intervals running. In production each runs once.
Preview
Console
Nothing logged yet.Expected console output
render Clock
render Clock
effect: start interval
cleanup: clear interval
effect: start interval`useState(initial)` uses its argument only on the first render. The prop changed, the copy didn't. Use the prop directly, or give `<Greeting key={name} />` to reset it on purpose.
Preview
Console
Nothing logged yet.Expected console output
prop: Asha | state copy: Asha
prop: Ravi | state copy: AshaType in both. The controlled box can't hold lowercase letters or more than six characters, because React state decides what it shows. The uncontrolled box keeps whatever you type until you read it.
Preview
Console
Nothing logged yet.**1. What happens when you call a state setter?** React queues the update with a lane (priority), schedules a render, calls the component again with the new state, diffs the result and commits the changes. The current render's variables don't change (Topic 4.4).
**2. Why are hooks called in the same order every render?** Hook state is a linked list on the fiber matched by call position. A conditional hook shifts every later hook onto the wrong slot (Topics 4.3, 26.1).
**3. What causes a component to re-render?** Its own state changing, its parent re-rendering, or a context it reads changing. Props changing is not a separate cause: props only change because the parent rendered (Topic 16.1).
**4. Re-render vs DOM update?** A re-render is calling the function. The DOM is touched only where the output differs (Topics 0.2, 4.8).
**5. What is batching?** Several setter calls in the same event (and since React 18, in timeouts and promises too) are applied in one render (Topic 4.5).
**6. `useEffect` vs `useLayoutEffect`?** Both run after the DOM is updated. Layout effects run before the browser paints and block it, for measuring and avoiding flicker. Normal effects run after paint (Topics 7.8, 26.1).
**7. What is the dependency array?** The list of reactive values an effect reads. React compares each with `Object.is`; if any changed, the old cleanup runs and the effect runs again. `[]` means "only after mount", no array means "after every commit" (Topic 7.2).
**8. `memo`, `useMemo`, `useCallback`?** `memo` skips a component's render when its props are shallow-equal. `useMemo` caches a calculated value; `useCallback` caches a function, so a memoised child sees the same prop. The React Compiler can add these automatically (Topics 16.3–16.5).
**9. Why must state be updated immutably?** React decides whether something changed by reference (`Object.is`). Mutating keeps the same reference, so React can skip the render and memoised children never see the change (Topics 4.6, 4.7).
**10. What is lifting state up?** Moving shared state to the closest common parent and passing it down with callbacks up (Topic 6.3).
**11. What is prop drilling and how do you fix it?** Passing props through many layers that don't use them. Fixes: composition with `children` first, then context, then an external store (Topics 9.1, 9.2, 15.2).
**12. When do context consumers re-render?** Every component that reads a context re-renders when the provider's `value` changes by reference, even if it uses only part of it. Split contexts or memoise the value (Topic 9.3).
**13. What are refs for?** Values that persist across renders without causing renders (timer ids, previous values) and handles to DOM nodes. Don't read or write `ref.current` during render (Topics 8.1, 8.2).
**14. How do events work in React?** Handlers receive a synthetic event that wraps the native one. Since React 17, React listens at the root container rather than `document`, and one listener per event type dispatches to your handlers through the fiber tree (Topic 4.1).
**15. What is an error boundary and what doesn't it catch?** A class component with `getDerivedStateFromError`/`componentDidCatch` that shows a fallback when a child throws during render, in lifecycles or constructors. It doesn't catch errors in event handlers, async code, or the boundary itself (Topics 14.5, 26.4).
**16. What is Suspense?** A boundary that shows a fallback while something inside is waiting (lazy code, `use(promise)`, a data library). With transitions, already-shown content stays visible instead of falling back (Topics 14.3, 16.7).
**17. `useTransition` vs `useDeferredValue`?** `useTransition` marks a state update you own as non-urgent and gives `isPending`. `useDeferredValue` gives a lagging copy of a value you receive, re-rendered in the background (Topic 16.7).
**18. What is hydration?** Attaching React to HTML the server already rendered: React renders the same tree on the client, adopts existing DOM nodes and wires events. Mismatches (dates, random values, browser-only APIs) cause warnings or a client re-render (Topic 20.6).
**19. Server Components vs Client Components?** Server Components run only on the server, can read data directly and send no JavaScript for themselves. Client Components (`"use client"`) run in the browser too and can use state, effects and event handlers. Props crossing the boundary must be serialisable (Topic 20.2).
**20. Derived state: store it or compute it?** Compute it during render. Storing it duplicates the source of truth and goes stale (Topics 6.1, 6.2, 7.6).
**21. Why shouldn't you define a component inside another component?** Each render creates a new function, so React sees a new type, unmounts the old subtree and loses its state (Topic 2.1).
**22. What's new in React 19?** Actions and `useActionState`, `useOptimistic`, `useFormStatus`, `use`, `ref` as a prop, `<Context>` as a provider, ref cleanup functions, document metadata, and resource preloading. React 19.2 added `<Activity>` and `useEffectEvent` (Phase 19, Topics 16.10, 7.9).
**23. How would you find why an app is slow?** Measure a production build with the React DevTools Profiler, find components that render often or slowly, then fix the cause: move state down, split context, memoise, virtualise or defer (Topics 16.6, 16.9).Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Switch an input from uncontrolled to controlled
In the controlled example, start the state as useState(undefined) instead of useState("") and type a letter.
Myth vs fact
Myth
The virtual DOM makes React faster than plain JavaScript.
Fact
Diffing is extra work. It makes a declarative model fast enough; hand-written DOM updates can always be faster for one specific change.
Myth
setState is asynchronous, so you can await it.
Fact
The setter returns nothing to await. It queues an update and schedules a render. The current render's variable never changes; read the new value in the next render or compute it yourself.
Myth
Index keys always cause bugs.
Fact
They are fine for static lists that never reorder, insert or delete in the middle. The bug appears when positions change while items have state or DOM state.
Myth
StrictMode double effects mean my app runs effects twice in production.
Fact
Only in development, and only on mount. It simulates an unmount and remount to check that your cleanup is correct.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Strong candidates connect answers to internals: keys and types are the inputs of reconciliation (Topic 16.2), the hook list lives on the fiber (Topic 26.1), and batching is lanes merging updates of the same priority.
- ▸
"Lifecycle" questions are often a trap for the class mental model. Saying "effects synchronise with external systems; I think in terms of which values an effect depends on" signals modern React experience (Topic 7.5).
- ▸
For controlled inputs in large forms, the cost is re-rendering on every keystroke. Mention the options: keep the field state local, use uncontrolled inputs with
FormData, a form library (Topic 5.7), oruseDeferredValuefor expensive previews.
Remember this
- 1
How to answer. A good interview answer has three parts: a one-sentence definition, the mechanism (what React actually does), and a consequence you have seen in real code (a bug it causes, or a rule it explains). For example, for keys: "keys tell React which item is which among siblings; React matches old and new children by key; so an index key on a list you reorder makes state stick to the wrong row." Interviewers listen for the mechanism; that is what separates memorising from understanding.
- 2
Virtual DOM. Rendering produces a tree of element objects (Topic 1.7). React compares the new tree with what it rendered last time (reconciliation, Topic 16.2) and commits only the differences to the real DOM (Topic 4.8). Its value is the programming model (describe the whole UI, let React find the changes), not raw speed. Under the hood the comparison is against fibers (Topic 26.1), and it uses two O(n) rules: a different element type means a new subtree, and children are matched by
key. - 3
Keys (Topic 3.3) identify an item among its siblings, so React can match it to the same fiber, state and DOM node across renders. They must be stable and unique among siblings. An index key is fine for a list that never reorders, inserts or deletes in the middle; otherwise state and DOM (typed text, focus, animations) stay at the old position and appear on the wrong item. The first live demo shows exactly that. Changing a component's
keyon purpose is also the cleanest way to reset its state (Topic 6.4). - 4
Controlled vs uncontrolled (Topics 5.1 and 5.3). A controlled input gets its
valuefrom React state and reports changes withonChange; React state is the single source of truth, so you can validate or transform as the user types. An uncontrolled input keeps its own value in the DOM; you give it a startingdefaultValueand read it when needed with a ref orFormData. Controlled gives control and costs a render per keystroke; uncontrolled is simpler for forms you only read on submit, and React 19 form actions (Topic 19.3) lean on it. Switching between the two during the component's life triggers a warning. - 5
State vs props (Topics 2.3 and 4.2). Props are inputs a parent passes down; the child must treat them as read-only. State is memory a component owns and changes with its setter, which schedules a re-render. A prop can become a child's initial state, but the copy won't follow later prop changes (the "mirror props in state" bug, Topic 6.2, shown live below): either use the prop directly, compute from it during render, or reset the child with a
key. - 6
Lifecycle in hooks (Topics 7.1–7.5). Function components don't have lifecycle methods; they synchronise. Mount, update and unmount map like this: an effect with
[]runs after the first commit and its cleanup on unmount; an effect with[a, b]re-syncs after commits whereaorbchanged, running the old cleanup first;useLayoutEffectruns before paint for measurements. Think "what must stay in sync with which values", not "what happens on mount". Class lifecycles and their mapping are in Topic 26.4. - 7
StrictMode (Topics 0.4 and 7.4) is a development-only checker. It renders components twice, runs effects setup → cleanup → setup once on mount, and (React 19) calls ref callbacks twice, to surface impure renders and missing cleanups. It does nothing in production. The third live demo shows the effect double-run. The full list of 20+ classic questions, with short model answers, is in the Q&A block under the examples; each one links to the topic that teaches it in depth.
Explain it without notes
What is the virtual DOM, and how does React use it to update the page?
Why do lists need keys, and when is the array index a bad key?
Explain controlled vs uncontrolled inputs. When would you use each?
What's the difference between state and props? What goes wrong if you copy a prop into state?
How do you express mount, update and unmount with hooks?
Practice
Write a TodoList that renders todos (objects with id and text) with correct keys and a delete button per item.
Make a Search component with a controlled input that trims leading spaces as you type and shows Searching for: <text> below it.
Write a Timer effect that logs tick every second while mounted and stops on unmount.
Trade-offs
- ↔
Controlled inputs give full control at the cost of a render per keystroke; uncontrolled inputs are cheaper and simpler but harder to validate live.
- ↔
Ids as keys need ids in your data. If items have none, generate them once when the data is created (not during render).
Done when you can
I can answer the virtual DOM, keys, controlled/uncontrolled, state/props and lifecycle questions in three beats.
I can demo the index-key bug and the batching surprise from memory.
I can explain what StrictMode does and why.
I can link each of the 20+ questions to the topic that teaches it.
I can explain the mirrored-prop bug and its two fixes.