Handbooks  /  The React Interview Handbook
Handbook~16 min readIntermediate
Interview Prep

React interviews,
and the render under it all.

React interviews rarely ask you to memorize an API. They probe whether you understand the model: UI as a function of state, why components re-render, and how hooks and reconciliation actually behave. Get that mental model and the questions answer themselves.

01

Components, JSX & the declarative model

A React app is a tree of components — functions that take inputs and return a description of UI written in JSX (which compiles to React.createElement calls). The defining idea is that React is declarative: you describe what the UI should look like for a given state, not the step-by-step DOM mutations to get there. The mental model is a single equation:

UI = f(state)

You never manually add or remove DOM nodes; you change state, and React figures out the DOM changes. This is the whole philosophy — and why the interview questions cluster around state, rendering, and how React turns your declarations into efficient updates.

02

Props vs state

Two kinds of data drive a component. Props are inputs passed in by a parent — read-only from the component's view; a component never mutates its own props. State is data a component owns and can change over time; updating it triggers a re-render.

Data flows one way: state lives in some component and flows down to children as props ("props down, events up" — children request changes by calling callbacks passed as props). A frequent interview point is lifting state up: when two components need the same data, you move that state to their nearest common parent and pass it down, keeping a single source of truth. Unidirectional flow is what makes React apps predictable.

→ The distinction

Props are read-only inputs from above; state is mutable data a component owns. If a value never changes within the component, it's a prop. If the component changes it over time and re-renders, it's state.

03

The render cycle & reconciliation

When state changes, React renders: it calls your component functions to produce a new tree of elements — the virtual DOM, a lightweight in-memory description of the UI. It then reconciles: diffs the new tree against the previous one and computes the minimal set of real DOM operations to make the browser match. The real DOM is slow to touch; the virtual DOM diff lets React batch and minimize those touches.

Rendering (calling your function) is not the same as committing to the DOM — React renders in memory, then commits only the differences. Understanding this split explains a lot: a re-render isn't automatically expensive DOM work, but it does run your component code and its diff, which is why avoiding unnecessary renders still matters at scale.

State change → render → reconcile → commit
1 · TriggerState/props change — schedules a re-render of the component (and descendants).
2 · RenderCall the component — produce a new virtual DOM tree (in memory, no DOM touched).
3 · ReconcileDiff new vs old tree — find the minimal changes.
4 · CommitApply just those changes to the real DOM.
04

Hooks & their rules

Hooks let function components use state and lifecycle features. The essentials: useState holds local state and returns a value + setter; useEffect runs side effects (data fetching, subscriptions) after render, controlled by a dependency array — it re-runs when a listed dependency changes, and its returned cleanup function runs before the next effect and on unmount (unsubscribe, clear timers). useMemo memoizes an expensive computed value; useCallback memoizes a function's identity.

The rules of hooks are a favorite interview question: only call hooks at the top level (never inside conditions, loops, or nested functions) and only from React function components or custom hooks. Why? React tracks hooks purely by their call order on each render — so the order must be identical every time, or state gets associated with the wrong hook. Break the rule and state silently corrupts.

→ The useEffect trap

The dependency array is the #1 hooks bug source. Omit a dependency and the effect uses stale values; include an unstable one (a new object/function each render) and it re-runs endlessly. Get the deps exactly right — and use the cleanup function for anything that subscribes or schedules.

05

Why re-renders happen — and memoization

A senior interview will push on performance. A component re-renders when: its state changes, its parent re-renders, or a context it consumes changes. The common problem is a parent re-render cascading to children that didn't need to update — often triggered by passing a new object or function reference as a prop each render (inline {} or () => creates a fresh reference, which looks like a changed prop).

The tools: React.memo skips a component's re-render if its props are unchanged (shallow-compared); useMemo keeps an object/computed value stable across renders; useCallback keeps a function identity stable so a memoized child doesn't see a "new" prop. But the crucial senior insight: memoization isn't free and isn't always a win — it costs memory and comparison, and applied everywhere it can make things slower and code noisier. Measure first, then memoize the hot paths that actually re-render too much.

ToolMemoizesUse to
React.memoA whole componentSkip re-render when props are unchanged
useMemoA computed value/objectAvoid recomputing, or keep a reference stable
useCallbackA function's identityStop a memoized child seeing a "new" function prop
06

Keys & list rendering

When you render a list, React needs a key on each item — a stable, unique identifier that tells reconciliation which item is which across renders. With keys, React can tell that an item moved, was added, or removed, and update efficiently while preserving each item's state.

The classic interview trap: using the array index as a key. It works until the list reorders, inserts, or deletes — then indexes shift, React mismatches items, and you get subtle bugs (an input's value attaching to the wrong row, wrong items animating). Use a stable id from your data, not the index. Keys are how React keeps identity straight in a dynamic list.

07

Controlled vs uncontrolled inputs

For form inputs, React distinguishes two patterns. A controlled component has its value driven by React state (value={x} + onChange) — React is the single source of truth, so you can validate, transform, and react to every keystroke. An uncontrolled component lets the DOM hold the value, and you read it via a ref when needed — simpler, less code, but you give up per-keystroke control.

Controlled is the React-idiomatic default and what interviewers usually expect, because it keeps the input consistent with your state model. Uncontrolled is fine for simple forms or integrating non-React widgets. The tell: if you need to know or shape the value as the user types, control it; if you just need the final value on submit, uncontrolled with a ref is lighter.

08

Context & state management

Prop drilling — threading a value through many intermediate components that don't use it — is a smell. Context solves it: provide a value at a high level and consume it anywhere below without passing props through every layer, ideal for app-wide data like theme, current user, or locale.

But context isn't a general state manager, and the senior nuance is a common question: every consumer re-renders when the context value changes, so putting frequently-changing state in one big context can cause broad re-renders. Split contexts by concern, memoize the provided value, and for complex or high-frequency state reach for a dedicated state library (Redux, Zustand, and friends) or server-state tools (React Query) rather than overloading context. Choose the lightest tool that fits: local state → lifting → context → a store, in that order of escalation.

→ The escalation ladder

Start with local useState. Shared between siblings? Lift it up. Needed app-wide and rarely changing? Context. Complex, high-frequency, or server data? A dedicated store or query library. Don't jump to Redux for a toggle.

Frequently asked

Quick answers

Props vs state?

Props are read-only inputs passed in by a parent; state is data a component owns and can change, triggering a re-render. Data flows one way: state down as props, changes up via callbacks.

Virtual DOM & reconciliation?

The virtual DOM is an in-memory UI description. On a state change React builds a new tree, diffs it against the old (reconciliation), and applies the minimal real-DOM updates — letting you write declarative code.

Why does a component re-render?

Its state changed, its parent re-rendered, or a context it uses changed. Unnecessary cascades from unstable props are fixed with React.memo, useMemo, and useCallback — but measure before memoizing.

The rules of hooks?

Call hooks only at the top level (not in conditions/loops) and only from components or custom hooks, because React tracks them by call order — the order must be identical every render.

Finished this one? 0 / 29 Handbooks done

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.