skip to content

React

3 roadmaps364 questionsupdated

React is the default frontend framework in interviews, so you are expected to explain it end to end. That means how components and JSX become elements, how hooks hold state and effects, how reconciliation decides what re-renders, and how the newer server/Suspense model splits work between server and client.

on this pageshow

guide

overview

~1 min

React is a library for describing a user interface as a function of state: you write components that return a description of the screen, and React works out which DOM changes turn the last description into the next one. Interviewers lean on it because so much frontend work runs through it, and because the gap between using React and understanding it shows quickly. Someone who can say *why* a component rendered, *when* an effect ran and *where* a piece of state should live debugs faster than someone who memorised the API. The hub follows that order of questions. [Components and JSX](/topics/fe-react-components-jsx) is the authoring surface: what JSX becomes, how props and children flow down, how events and forms are wired. [Built-in hooks](/topics/fe-react-hooks) covers the contract of each hook, and [state and context](/topics/fe-react-state-context) turns those hooks into architecture: where state lives, how it is shaped, how it is shared. [Effects and lifecycle](/topics/fe-react-effects-lifecycle) is how a component reaches outside itself, and where most real bugs sit. [Rendering and reconciliation](/topics/fe-react-reconciliation) explains the engine underneath — what schedules a render, how the tree is compared, what gets committed — and [performance and memoization](/topics/fe-react-performance) builds on it. [Server Components and Suspense](/topics/fe-react-server-suspense) is the newer model, where part of the tree never reaches the browser. Junior rounds check the model: props against state, the dependency array, keys in a list, controlled inputs. Middle rounds bring stale closures, effect cleanup and re-render causes. Senior and principal rounds turn into design conversations — where state belongs, when memoization pays, what belongs on the server — and expect reasons rather than reflexes. Learn components and the core hooks first, then the render-and-commit cycle, because effects, performance and the server model all assume it.

primer

### UI is a function of state A component is a function from props and state to a description of UI. It does not change the screen; it returns elements, plain objects, and React decides what to write to the DOM. Rendering should therefore be pure: same inputs, same output, no side effects in the body. Most rules that feel arbitrary — no mutation, no setState during render, effects kept separate — follow from that single constraint. ### Each render is a snapshot Every render sees its own props and state as constants. A setter does not change the variable you are holding; it asks React for a future render with a new value. Handlers, effects and timers close over the render that created them. Stale values, updates that seem lost and intervals that stop counting are all the same idea met from different sides, and interviewers use them to test whether you hold the model or only the syntax. ### Hooks are identified by call order React keeps a component's hook state in slots and finds each one by position, not by name. That is where the rules of hooks come from — top level only, same order on every render — and why custom hooks compose freely: a custom hook is just more calls in the same sequence. Break the order and one hook quietly reads another's data. ### Render, then commit, then effects Work happens in phases. **Render** calls your components and compares the result with the previous tree; it can run more than once, be paused or be thrown away. **Commit** applies the changes to the DOM in one pass. Effects run after commit, layout effects before the browser paints and passive effects, usually, after it. Knowing which phase a line of code belongs to answers most timing questions. ### Identity decides what survives React keeps state attached to a position in the tree, qualified by element type and `key`. The same type at the same position updates in place; a different type or key starts over, state and DOM included. That makes keys a tool for resetting state deliberately, and not only a way to silence a warning on lists. ### Effects synchronise with the outside world An effect keeps something outside React — a subscription, a socket, a timer, a DOM API — in step with the current render, and its cleanup undoes the previous setup. An effect that only copies one piece of state into another is usually a mistake: derive the value during render instead. Senior rounds probe whether you can tell an effect that synchronises from one that patches the data flow. ### Re-renders are cheap until they are not A component renders again when its state changes, a context it reads changes, or its parent renders. That is by design, and most renders cost little. Memoization trades memory and comparison work for skipped renders, and only helps when references stay stable. The strong answer measures first and often fixes the cost by moving state or restructuring the tree rather than by wrapping components. ### The tree spans two runtimes With Server Components, part of the tree runs only on the server and sends its output, not its code; client modules ship to the browser and hold the interactivity. Suspense boundaries mark where the UI may wait and stream in later. Questions here are about placement: what runs where, what may cross the boundary, and what that does to bundle size and first paint.

Element
An immutable plain object describing what to render: a type, props and an optional key. Components return elements; React turns them into DOM.
JSX
Syntax that compiles to function calls creating elements. It is not HTML: attributes are props, and expressions go in braces.
Hook
A function whose name starts with use and which reads or registers React-managed state or behaviour. Called only at the top level of components and other hooks.
Dependency array
The list of values that decides whether an effect or memoized value is recomputed. React compares each entry with the previous render's using Object.is.
Effect cleanup
The function an effect returns. React calls it before the effect runs again and when the component unmounts, to undo the previous setup.
Controlled input
A form field whose value comes from React state and changes only through a handler, as opposed to one whose value lives in the DOM.
Context
A way to pass a value to any descendant without threading props. It carries a value; the state behind it still lives somewhere else.
Fiber
React's internal unit of work: one node per component or host element, holding its state, props and links to parent, child and sibling.
Reconciliation
Comparing the new element tree with the previous one to decide which fibers to keep, update, create or delete.
Key
A prop that gives an element an identity among its siblings, so React can match it across renders independently of its position.
Batching
Grouping several state updates into one render. Since React 18, with createRoot, this happens automatically, including inside promises and timeouts.
Transition
An update marked non-urgent, which React may interrupt or abandon so urgent input such as typing stays responsive.
Suspense boundary
A component that shows a fallback while something inside it is not ready, such as lazy code or data, then reveals the content.
Hydration
Attaching React to HTML already rendered on the server: the client renders the same tree and adopts the existing DOM instead of recreating it.
Server Component
A component that runs only on the server. Its output is sent to the client, its code is not, and it cannot hold state or handle events.
'use client'
A directive at the top of a module that marks where the client bundle begins. That module and everything it imports ship to the browser.
Error boundary
A component that catches errors thrown while rendering its subtree and shows fallback UI in its place. Still written as a class.

Follow one interaction through the system. A click runs a handler, which calls a setter; React queues the update and, once the handler finishes, renders the component that owns that state and everything beneath it. Each component returns elements, and reconciliation walks the new elements against the existing fiber tree, matching them by type and key and bailing out where it can prove nothing changed. The commit applies the difference to the DOM, attaches refs, runs layout effects, and then, usually after the browser has painted, runs passive effects — cleanups of the previous render first. Every other section of this hub is a view of one step on that path: - **Components, JSX and hooks** are what you write at the start of it; the hooks' contracts decide what each render sees. - **State and context** decide *which* component owns the update, and therefore how much of the tree renders again. - **Effects** live at the end of the path, and their dependency arrays decide whether they run at all. - **Reconciliation** is the middle; batching, update queues and concurrent rendering change when and how often it runs. - **Performance** work removes steps from the path: fewer components rendered, less work per render, less code loaded before first paint. The server model extends the same tree across a network boundary. Server Components render first, on the server, and their output travels to the browser alongside the client components they reference; Suspense marks the places that may stream in later; hydration then attaches the client runtime to HTML that already exists. A single page file shows several of these ideas meeting: ```jsx // page.jsx: a Server Component; its code never reaches the browser export default async function Page({ id }) { const user = await loadUser(id); // data read on the server return ( <> {/* ProfileForm lives in a 'use client' module; its props are serialized */} <ProfileForm key={user.id} user={user} /> <Suspense fallback={<OrdersSkeleton />}> <Orders userId={user.id} /> {/* async child, streamed in later */} </Suspense> </> ); } ``` The `key` gives the client form fresh state per user, the prop crossing into the client module must be plain data, and the boundary lets the page show the profile before the orders are ready.

  1. Components and JSX →

    What JSX compiles to, and how props, children and events move through a tree; the vocabulary every other section uses.

  2. Built-in Hooks →

    The contract of each built-in hook, including call order and dependency arrays, which most later bugs trace back to.

  3. State and Context →

    Where state should live and how it is shared, which decides how much of the tree renders on each update.

  4. Rendering and Reconciliation →

    The render and commit cycle, keys and batching: the engine that makes timing and re-render questions answerable.

  5. Effects and Lifecycle →

    Effects, cleanup, refs and StrictMode, easier once you know when the commit happens and what each render captures.

  6. Performance and Memoization →

    Memoization, profiling and splitting build on reconciliation; learn it after, so each technique has a clear cost.

  • Saying a component re-renders because its props changed: props change because the parent rendered, and state or a context it reads are the other triggers.

  • Reading state right after calling its setter and expecting the new value; the setter schedules a future render, and the current one keeps its snapshot.

  • Using useEffect to keep one piece of state in sync with another, when the value could be computed during render with no extra pass.

  • Leaving a value out of the dependency array to stop an effect re-running, instead of changing what the effect reads — the usual source of stale closures.

  • Using the array index as a key for lists that reorder, insert or delete; state and DOM stay with the position, not the item.

  • Wrapping everything in React.memo, useMemo and useCallback by reflex, without measuring, and without noticing that one unstable prop makes the comparison fail every time.

  • Treating Context as a state manager: it only delivers a value, and every consumer renders again when that value's identity changes.

  • Calling the double effect run in development a bug to be suppressed; StrictMode is exposing an effect whose cleanup does not undo its setup.

  • Adding 'use client' to the top of the tree to make an error go away, which moves everything it imports into the browser bundle.

This guide assumes React 19, where Server Components, Actions and the `use` API are stable. Interviewers still ask about the releases that shaped today's model, because many codebases sit on older versions: - **16** replaced the reconciler with **Fiber**, which made rendering interruptible and introduced error boundaries. - **16.8** added **hooks**; function components could hold state and effects, and class lifecycles stopped being the default way to write React. - **17** attached event listeners to the root container instead of the document and introduced the new JSX transform, so files no longer needed to import React for JSX. - **18** introduced `createRoot` and concurrent features: automatic batching outside event handlers, transitions, `useDeferredValue`, `useId`, `useSyncExternalStore`, and streaming server rendering with Suspense. StrictMode began mounting components twice in development to surface effects without cleanup. - **19** added Actions and the form hooks `useActionState`, `useFormStatus` and `useOptimistic`, the `use` API, `ref` as an ordinary prop for function components, and rendering a context directly as its provider. It also removed long-deprecated APIs, such as `ReactDOM.render` and string refs. The React Compiler is a separate build-time tool that inserts memoization automatically, which changes how much hand-written `useMemo` and `useCallback` a codebase needs. When an answer depends on batching, effect double-runs or how refs reach a function component, name the version you are describing.

React is a rendering library, not a full application framework, so interviewers expect you to name what sits around it. Routing, data loading and server rendering usually come from a framework: Next.js and React Router are the common choices, and Server Components need a framework or bundler integration to work at all. Server data is typically handled by a query library such as TanStack Query, which caches, deduplicates and revalidates requests, rather than by effects written by hand. Shared client state goes to `useReducer` with context, or to an external store such as Redux Toolkit or Zustand when many components subscribe to parts of a large state. Forms, tests and styling have their own common picks, with React Testing Library the usual answer for component tests. Among UI frameworks, React competes most directly with Vue, Angular, Svelte and Solid. The trade-off an interviewer expects you to state is the rendering model: React re-runs components and compares their output, while frameworks built on fine-grained reactivity, such as Solid and Svelte, track which values each piece of UI reads and update only those parts. React's answer to that cost is memoization, now increasingly automated by its compiler; the others' answer is finer-grained reactivity with a different authoring model. React Native carries the same component and hook model to mobile platforms.

explore

report an issue with this guide →

questions

364 · 7 sections

In React 19, what exactly is a function component, how does it differ from a class component, and is there anything a class can still do that a function cannot?

level: juniorimportance: must knowfreq 80%
basics
~20 s

A function component is a plain function that takes a props object and returns React elements, using hooks for state and effects. A class extends React.Component and implements render() plus lifecycle methods. Only error boundaries still require a class.

open as a page

In React, an inline handler such as onClick={() => setOpen(true)} is a brand-new function on every render. Why does that happen, and when is it actually a problem?

level: juniorimportance: must knowfreq 78%
basics
~20 s

Every render re-runs the component body, so the arrow expression evaluates again into a new function object. The allocation itself is cheap; the new identity only matters where something compares it, such as a memoized child or a dependency array.

open as a page

In React JSX, what is the difference between writing onClick={handleClick} and onClick={handleClick()}, and what actually happens with the second form?

level: juniorimportance: must knowfreq 72%
basics
~20 s

The first passes the function so React can call it on click. The second calls it during render and passes its return value, usually undefined, so nothing happens on click and the side effect fires on every render.

open as a page

In a React onSubmit or onClick handler, why does `return false` not stop the browser's default behaviour, and what do you write instead?

level: juniorimportance: must knowfreq 50%
basics
~10 s

React ignores a handler's return value entirely. Returning false only cancels defaults in inline HTML attributes and jQuery handlers. In React you call e.preventDefault(), and e.stopPropagation() separately if you also want to stop bubbling.

open as a page

In React 19, what object does React pass to an event handler such as onClick, and how do you reach the underlying browser event from it?

level: juniorimportance: must knowfreq 65%
basics
~10 s

React passes a SyntheticEvent: a cross-browser wrapper that mirrors the DOM event interface (type, target, preventDefault, stopPropagation). The untouched browser event is always available on e.nativeEvent for anything React does not normalize.

open as a page

In React, from which functions may you call a hook such as useState, and which common call sites are forbidden?

level: juniorimportance: must knowfreq 70%
basics
~20 s

Hooks may be called only from the top level of a React function component body or from another hook (a function whose name starts with "use"). Event handlers, plain helper functions, class components, and nested callbacks are all forbidden.

open as a page

In React, what does the argument passed to createContext(defaultValue) actually do, and what does useContext(MyContext) return when no matching provider is mounted above the component?

level: juniorimportance: must knowfreq 72%
basics
~20 s

createContext's argument is a fallback used only when no matching provider sits above the consuming component. useContext then returns it silently instead of throwing. It is not an initial value, and a mounted provider never falls back to it.

open as a page

In React, what is the difference between calling useEffect(fn) with no second argument, useEffect(fn, []) with an empty array, and useEffect(fn, [a, b])?

level: juniorimportance: must knowfreq 85%
basics
~20 s

The second argument controls re-runs: omitting it runs the effect after every render, an empty array runs it once after mount, and a populated array re-runs it only when one of the listed values changes.

open as a page

In React, what is the difference between useMemo(factory, deps) and useCallback(fn, deps), and how are the two related?

level: juniorimportance: must knowfreq 80%
basics
~10 s

useMemo calls the factory you pass and caches its return value; useCallback caches the function itself without ever calling it. They are one mechanism: useCallback(fn, deps) behaves exactly like useMemo(() => fn, deps).

open as a page

In React, what arguments does useReducer take and what does it return, and what happens when you call the dispatch function it gives you?

level: juniorimportance: must knowfreq 68%
basics
~20 s

useReducer takes a reducer function, an initial value, and an optional init function. It returns the current state and a dispatch function; calling dispatch with an action schedules an update whose next state React computes by running the reducer.

open as a page

When a React context provider is rendered with a new value, which components re-render because of that context change — every descendant of the provider, or only the ones that read the context?

level: juniorimportance: must knowfreq 62%
basics
~20 s

Only components that read that context re-render because of the change. React notifies the consumers it finds below the provider. Other descendants re-render for a different reason: their own parent re-rendered and re-created their elements.

open as a page

Is React Context a state-management library? Explain what Context actually provides, and what it does not provide compared with an external store such as Redux or Zustand.

level: juniorimportance: must knowfreq 70%
basics
~20 s

React Context is a dependency-injection channel, not a state manager: it carries one value down the tree so descendants can read it without prop drilling. It stores nothing itself — the state still lives in useState, useReducer, or an external store.

open as a page

In React, when should logic inside a component be extracted into a custom hook, and when is a plain JavaScript function the better choice instead?

level: juniorimportance: must knowfreq 74%
basics
~20 s

Extract a custom hook when the logic calls other hooks, or when the same hook wiring repeats across components. If the logic is a pure computation over its arguments, keep it a plain function outside the component.

open as a page

In React, two sibling components need the same value — one displays it and the other edits it. Where does that state go, and what does each sibling receive instead?

level: juniorimportance: must knowfreq 78%
basics
~20 s

Move the state into the siblings' nearest common ancestor. That parent owns it with useState and passes the current value down to both children, plus a callback that lets the editing child ask for a change.

open as a page

A React component holds `firstName` and `lastName` in useState and keeps a third `fullName` state in sync with a useEffect that calls setFullName(firstName + ' ' + lastName). What is wrong with this, and what would you write instead?

level: juniorimportance: must knowfreq 72%
basics
~20 s

fullName is derivable, so storing it duplicates state. The effect runs after React commits, so the screen briefly shows a stale name and every keystroke costs a second render pass. Compute it during render as a plain const.

open as a page

In React, a component polls by calling setInterval inside a useEffect. What must that effect return, and what goes wrong on a screen the user opens and leaves repeatedly?

level: juniorimportance: must knowfreq 62%
basics
~20 s

The effect must return a cleanup function that calls clearInterval with the id setInterval returned. Without it, every mount leaves another live timer behind, so abandoned components keep polling forever and traffic multiplies with each visit.

open as a page

A React component loads its data by calling `fetch` inside `useEffect` and storing the result with `useState`. Why does that component always render at least once with no data, and what does that force you to write by hand?

level: juniorimportance: must knowfreq 72%
basics
~10 s

Effects run after React has rendered and committed the component, so the first render happens before the request is even sent. Every fetch-in-effect component therefore needs hand-written loading, error and empty states.

open as a page

In React, what is the difference between calling useEffect(fn) with no second argument, useEffect(fn, []), and useEffect(fn, [a, b])?

level: juniorimportance: must knowfreq 80%
basics
~20 s

Omitting the second argument runs the effect after every render. An empty array runs it once after mount, with cleanup at unmount. A list of values re-runs it whenever any listed value changes, compared with Object.is.

open as a page

In a React component, a Buy button must POST an order and then show a confirmation toast. One version does both inside the onClick handler; another sets `ordered` state in the handler and runs `useEffect(() => { if (ordered) { postOrder(); showToast(); } }, [ordered])`. Which is correct, and why?

level: juniorimportance: must knowfreq 68%
basics
~20 s

Both belong in the onClick handler: they are caused by a specific user action, not by the component being displayed. Routing them through state and an effect adds a render pass, an extra state field, and a path for the request to fire twice.

open as a page

In a React component you subscribe to a media query with window.matchMedia('(max-width: 600px)') inside useEffect. What must that effect return, and what goes wrong in an app that mounts and unmounts that component many times if it doesn't?

level: juniorimportance: must knowfreq 65%
basics
~20 s

The effect must return a cleanup function that removes the exact listener it added. Without it, every mount leaves another live listener on the MediaQueryList, so subscriptions pile up, unmounted components keep reacting, and the retained closures leak memory.

open as a page

In a React 19 component, one click handler calls setCount, setName and setOpen one after another, yet the component body logs only one render. What is automatic batching, and why does React work this way?

level: juniorimportance: must knowfreq 72%
basics
~20 s

Automatic batching means React collects every state update queued while the current work runs and applies them in a single re-render instead of rendering once per setter. It avoids wasted renders and half-updated intermediate UI.

open as a page

In a React function component that renders <input ref={inputRef} />, reading inputRef.current in the component body gives null, but reading it inside an effect gives the DOM element. What happens in between?

level: juniorimportance: must knowfreq 60%
basics
~20 s

Rendering only computes what the UI should be, so no DOM node exists yet and the ref is still null. React then commits that output: it creates the DOM nodes, attaches refs to them, and only afterwards runs your effects.

open as a page

In a React 19 search box, the onChange handler calls setQuery(value) directly but wraps setFilterTerm(value) in startTransition. Why must the input's own state update stay outside the transition?

level: juniorimportance: must knowfreq 55%
basics
~20 s

The typed value is urgent: React must commit it right away or the characters the user typed appear late. An update marked with startTransition is non-urgent and interruptible, so putting the input's own value in one makes the field feel stuck.

open as a page

In React, the element at one position in the tree is a <div> on one render and a <section> on the next, with identical children inside. What does React do with that node and everything beneath it?

level: juniorimportance: must knowfreq 68%
basics
~20 s

React tears down the old subtree and builds a new one: DOM nodes are recreated, component state is lost, effect cleanups run and refs detach. Types must match at a position for React to update in place.

open as a page

React is usually described as using a "virtual DOM". Concretely, what is that virtual DOM made of, and is updating it faster than updating the real DOM directly?

level: juniorimportance: must knowfreq 80%
basics
~20 s

React's virtual DOM is a tree of plain JavaScript objects describing the intended UI. They are cheap to create, so React can compare them and write only the DOM that changed — not faster than optimal manual DOM work, just easier.

open as a page

In React 19, how does React.lazy let a route component ship in its own chunk — what must the imported module expose, and what must be present in the tree when the lazy component first renders?

level: juniorimportance: must knowfreq 70%
basics
~20 s

React.lazy(() => import('./Page')) returns a component whose code loads on first render. The imported module must expose that component as its default export, and the lazy element must render inside a Suspense boundary that supplies a fallback.

open as a page

In React, a component is wrapped in React.memo. Which re-renders does that actually skip, and which does it not prevent?

level: juniorimportance: must knowfreq 62%
basics
~20 s

React.memo skips a re-render caused by the parent, and only when every new prop is the same as the old one by a shallow comparison. Its own state updates, a context change it reads, or any changed prop still re-render it.

open as a page

Both React.memo and useMemo are described as memoization in React, and candidates often use the names interchangeably. What does each one actually cache, and when would you reach for one rather than the other?

level: middleimportance: must knowfreq 72%
basics
~20 s

React.memo caches a component's rendered output and skips re-running it when its props are unchanged. useMemo caches one value inside a component that still re-renders. One avoids a render; the other avoids a computation during a render.

open as a page

What does the React Compiler (babel-plugin-react-compiler) do to your components at build time, and which hand-written memoization does it make redundant?

level: middleimportance: must knowfreq 60%
basics
~20 s

The React Compiler is a build-time Babel plugin that rewrites components to cache their derived values and their JSX in per-instance slots, reusing them when inputs are unchanged. It replaces most hand-written useMemo, useCallback and React.memo.

open as a page

In a React component, `const query = { term, page };` is built in the component body and used as `useEffect(() => { fetchResults(query).then(setRows); }, [query]);`. The effect fires after every render and never settles. Explain the mechanism and give two fixes.

level: middleimportance: must knowfreq 68%
basics
~20 s

Rebuilding query in the component body creates a new object on every render, and React compares each dependency with Object.is, so the effect re-runs, sets state, renders again, and loops. Depend on the primitive fields instead.

open as a page

In React 19 you can pass a function to a <form> element's action prop instead of writing an onSubmit handler. What does React take over on your behalf when you do that?

level: juniorimportance: must knowfreq 62%
basics
~20 s

React calls the function with the form's FormData, prevents the default navigation itself, and runs the call as an Action inside a transition — so React tracks pending state, surfaces errors, and resets an uncontrolled form after it succeeds.

open as a page

In React, what does the fallback prop of <Suspense> render, and what decides when the user sees the fallback instead of the boundary's children?

level: juniorimportance: must knowfreq 70%
basics
~20 s

The fallback prop holds the UI React shows in place of a <Suspense> boundary's children while something inside those children is not ready yet. React swaps the real children back in as soon as nothing inside that boundary is suspended.

open as a page

In React 19, props passed from a Server Component to a Client Component are serialized into the RSC payload before they reach the browser. Which kinds of values survive that trip, and which ones make React throw?

level: juniorimportance: must knowfreq 68%
basics
~20 s

Primitives, plain objects, arrays, Date, Map, Set, typed arrays, JSX elements, promises and Server Functions can cross. Ordinary functions, class instances and locally created symbols throw, because React must write every prop into a wire payload the browser reads back.

open as a page

In a React 19 app that uses React Server Components, what is the fundamental difference between a Server Component and a Client Component?

level: juniorimportance: must knowfreq 78%
basics
~20 s

Server Components execute only on the server, once per request, and their code never ships to the browser. Client Components are sent to the browser as JavaScript, where they mount, hold state, and respond to user input.

open as a page

In a React Server Components app, a file that starts with 'use client' imports a Button from another file that has no directive. Is that Button a client component, does its own file need a 'use client' line, and where in a file must the directive be written?

level: juniorimportance: must knowfreq 62%
basics
~20 s

Yes, the Button is a client component. Files below a client boundary inherit it through imports and need no directive of their own. The directive must be the first statement of a file, above every import.

open as a page