These 60 React interview questions cover what interviews ask most: JSX, props and state, hooks such as useState and useEffect, keys, rendering and memo, context, error boundaries, Server Components and React 19 additions like useActionState. Each has a short answer in plain words, many with code, and you can filter by topic and level.
| Topic | Questions |
|---|---|
| Basics | 10 |
| Hooks | 12 |
| State and data | 8 |
| Rendering and performance | 10 |
| Patterns | 7 |
| Modern React | 7 |
| Testing and practice | 6 |
Updated
Use the filters to drill one area, open an answer only after you have said yours out loud, and read the code samples as the kind of thing an interviewer may ask you to write on the spot.
Shaky on re-renders? Watch them counted live in React memo, useMemo and useCallback.
Junior. A JavaScript library for building user interfaces from components. You describe what the screen should look like for the current data, and React updates the page when the data changes.
Junior. A syntax that looks like HTML inside JavaScript. A build step turns each tag into a function call that creates a React element, so you can use any JavaScript expression inside curly braces.
const name = "Ada";
const el = <h1 className="title">Hello, {name}</h1>;Junior. A function that takes props and returns JSX. Names start with a capital letter so React can tell them apart from HTML tags.
Junior. The inputs a parent passes to a child component, like attributes on an HTML tag. A component must not change its own props; it receives new ones when the parent re-renders.
Junior. Props come from the parent and are read-only inside the component. State belongs to the component itself and changes over time through its setter, which triggers a re-render.
Junior. Keys tell React which item is which between renders, so it can keep the right state and DOM node with each item when the list is reordered, filtered or added to. Use a stable id from your data, not the array index when the order can change.
{todos.map((t) => <TodoItem key={t.id} todo={t} />)}Junior. Use plain JavaScript: an if before the return, the ternary operator inside JSX, or && for show-or-nothing. Be careful with && and numbers: 0 && <X /> renders a 0.
{items.length > 0 && <List items={items} />}
{isAdmin ? <AdminBar /> : null}Junior. A wrapper that groups several elements without adding a DOM node. Write <>...</>, or <Fragment key={...}> when the group needs a key in a list.
Junior. Pass a function to a camelCase prop such as onClick. React passes a synthetic event that behaves like the browser event. Pass the function itself, not the result of calling it.
<button onClick={() => setCount(count + 1)}>Add</button>Junior. The description of the UI as plain objects that React builds on each render. React compares the new description with the last one and applies only the differences to the real DOM. That comparison is called reconciliation.
Junior. It gives a component a piece of state and a function to update it. Calling the setter schedules a re-render with the new value; the variable in the current render does not change.
const [count, setCount] = useState(0);Mid. When the next value depends on the previous one, especially with several updates in one event. Each updater receives the latest queued value, whereas setCount(count + 1) twice uses the same stale count both times.
Junior. Synchronising with something outside React after render: a subscription, a timer, a non-React widget or a network request. The dependency array says when to run it again, and the returned function cleans up.
useEffect(() => {
const id = setInterval(tick, 1000);
return () => clearInterval(id);
}, []);Mid. To compute values from props or state (calculate them during render instead), or to react to a user event (do the work in the event handler). Effects are for syncing with external systems.
Junior. Call hooks only at the top level of a component or custom hook, never inside loops, conditions or nested functions, and only from React functions. React relies on the call order being the same every render.
Mid. Holding a value that survives renders without causing one when it changes, such as a DOM node, a timer id or a previous value. Read and write it through ref.current.
Mid. useMemo caches the result of a calculation; useCallback caches a function. Both return the same thing until a dependency changes, and both mainly matter when passing values to memoised children.
Mid. A way to read a value provided higher in the tree without passing props through every level. Every component that reads a context re-renders when its value changes.
const ThemeContext = createContext("light");
function Button() {
const theme = useContext(ThemeContext);
return <button className={theme}>OK</button>;
}Mid. When several values change together or the next state depends on an action type, such as a form wizard or a cart. The reducer keeps all transitions in one testable function.
Mid. A function whose name starts with use and that calls other hooks. It shares stateful logic between components; each component that calls it gets its own state.
function useOnline() {
const [on, setOn] = useState(navigator.onLine);
useEffect(() => {
const up = () => setOn(true), down = () => setOn(false);
addEventListener("online", up); addEventListener("offline", down);
return () => { removeEventListener("online", up); removeEventListener("offline", down); };
}, []);
return on;
}Senior. It runs after React changes the DOM but before the browser paints, so you can measure layout and adjust without a visible flicker. It blocks painting, so use it only for that.
Mid. Generating a unique id that matches between server and client rendering, for linking labels, inputs and descriptions. It is not meant for list keys.
Junior. Moving shared state to the closest common parent of the components that need it, then passing it down as props along with functions to change it.
Mid. React decides whether to re-render by comparing the old and new value. Mutating an object or array in place keeps the same reference, so React may skip the update. Create a new copy instead.
setTodos((t) => [...t, newTodo]);
setUser((u) => ({ ...u, name: "Lin" }));Mid. A controlled input gets its value from state and reports changes through onChange. An uncontrolled input keeps its own value in the DOM, which you read with a ref or a form submit.
Mid. A value you can calculate from existing props or state, such as a filtered list. Storing it separately means keeping two copies in sync; calculating it during render cannot drift.
Mid. Passing props through components that do not use them just to reach a deep child. Fixes include composition (passing children), context, or a state library for truly global data.
Senior. When many distant components read and update the same client state and context causes too many re-renders, or when you need tools such as devtools and middleware. Server data is usually better handled by a data-fetching library that caches it.
Mid. In a framework with Server Components, fetch on the server. On the client, use a data library or an effect that starts the request, handles loading and errors, and ignores the result if the component unmounted or the input changed.
useEffect(() => {
let ignore = false;
fetch(`/api/user/${id}`).then((r) => r.json()).then((u) => { if (!ignore) setUser(u); });
return () => { ignore = true; };
}, [id]);Senior. No. Updates are queued and batched; React 18 and later batch updates from timeouts and promises too, not only from event handlers. The new value appears in the next render.
Mid. Its state changes, its parent re-renders, or a context it reads changes. A re-render does not always change the DOM; React updates only what differs.
Mid. It skips re-rendering a component when its props are shallowly equal to last time. It pays off only when the component renders often with the same props and its render is not cheap.
Mid. A development-only wrapper that runs extra checks: it renders components and runs effects twice to expose side effects and missing cleanup. It does nothing in production.
Senior. Record the interaction in the React DevTools Profiler on a production build, look for components that render often or take long, then fix the cause: move state down, memoise, or virtualise long lists.
Senior. A way to mark an update as not urgent. React keeps the input responsive and can interrupt the slow render, and isPending lets you show that work is in progress.
Senior. It gives you a copy of a value that may lag behind during heavy rendering. Typing updates the input at once while the expensive list renders with the deferred value.
Mid. Virtualise it: render only the rows in view with a library such as react-window or TanStack Virtual. Paging or loading more on scroll also limits the number of DOM nodes.
Mid. Loading parts of the app only when they are needed. React.lazy with a dynamic import and a Suspense fallback splits a component into its own file.
const Settings = lazy(() => import("./Settings"));
<Suspense fallback={<Spinner />}><Settings /></Suspense>Senior. Attaching React to HTML that was rendered on the server, so the existing markup becomes interactive without being rebuilt. If the client renders something different, React reports a hydration mismatch.
Senior. A build-time tool that analyses components and adds memoisation automatically, so much hand-written useMemo, useCallback and memo becomes unnecessary. It expects code that follows the rules of React.
Mid. Building components by putting others inside them, often through children or other props. React components share behaviour through composition and hooks, and the React team has not found a case where inheritance hierarchies help.
Mid. Whatever you put between a component's opening and closing tags. It lets a layout or wrapper component render content it does not know about.
function Card({ children }) {
return <div className="card">{children}</div>;
}
<Card><p>Any content</p></Card>Senior. A function that takes a component and returns a new one with extra behaviour. Custom hooks replaced most uses, because they share logic without wrapping and renaming props.
Senior. A component that catches errors thrown while rendering its children and shows a fallback instead of a blank page. It is still written as a class with getDerivedStateFromError, or with a small library.
Mid. Rendering children into a different DOM node, such as document.body, with createPortal. It is used for modals and tooltips that must escape a parent's overflow or stacking.
Mid. In React 19, function components accept ref as a normal prop. In earlier versions, wrap the child in forwardRef. Use useImperativeHandle to expose only certain methods.
Senior. A group of components that work together and share state through context, such as Tabs with Tabs.List and Tabs.Panel. The user arranges the parts while the parent manages the logic.
Mid. Components that run only on the server and send their rendered result, not their code, to the browser. They can read data directly; interactive parts go in Client Components marked with "use client".
Mid. It marks a file as the start of client code: that module and what it imports are bundled for the browser and can use state, effects and event handlers.
Senior. Async functions that run on the server but can be called from the client, most often as a form action. Treat each one as a public endpoint: validate input and check permissions.
Mid. It wraps an action function and returns its latest result, a wrapped action to pass to a form, and a pending flag. It is the React 19 way to show form feedback.
const [state, action, pending] = useActionState(save, { error: null });
<form action={action}>...</form>Senior. A React 19 API that reads the value of a promise or a context during render. Unlike hooks it may be called inside conditions; with a promise it suspends until the value is ready.
Senior. It shows the expected result of an action straight away, such as a new comment, while the request is still running, then settles on the real result when it returns.
Mid. A component that shows a fallback while something inside it is not ready, such as lazily loaded code or data in a framework that supports it. With server rendering, it lets parts of the page stream in later.
Mid. Render it with React Testing Library in a test runner such as Vitest or Jest, interact the way a user would (click, type), and assert on what is visible, not on internal state.
Mid. Queries such as getByRole("button", { name: "Save" }) find elements the way assistive technology does, so tests also check that the UI is accessible and survive markup changes.
Junior. The React docs recommend starting with a framework such as Next.js or React Router for full apps. For a client-only app, Vite is a common build tool.
Mid. Use semantic HTML elements, label every input, manage focus in dialogs, keep keyboard access for anything clickable, and test with a screen reader and an automated checker.
Senior. Serve real HTML for each URL through server rendering, static generation or prerendering, give every route its own title and meta description, and list the URLs in a sitemap.
Senior. Correct keys in lists, effects with complete dependencies and cleanup, no state that could be derived, accessible markup, error and loading states, and no secrets in client code.
Several answers here have their own deep-dive pages with live demos: memo, useMemo and useCallback with render counters, Server Components with a boundary diagram, and forms with React Hook Form.
State and props, hooks (especially useEffect and its dependency array), keys in lists, re-rendering and memoisation, context, and data fetching. Senior roles add performance profiling, architecture and Server Components.
Less and less. New code uses function components and hooks. It still helps to recognise lifecycle methods when reading older code, and error boundaries are still written as classes.
Build small things from scratch: a todo list, a search box with a debounced fetch, a modal with focus handling. Talk while you code and test edge cases such as empty lists and errors.
Increasingly, at least at the level of knowing them: ref as a prop, actions with useActionState, useOptimistic, the use API and Server Components.
Related: React memo, useMemo and useCallback, React Server Components, React Hook Form examples, Promises, async/await and fetch, All free tools.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.