DevAcademy
All interview questions
126+ Questions

React Interview Questions & Answers

Curated React interview questions with detailed answers, grouped by topic. Search, revise and get interview-ready.

Filter by difficulty:

React Introduction

Q1. What is React?

A JavaScript library, created by Meta, for building user interfaces declaratively out of reusable components. You describe what the UI should look like for a given state, and React handles updating the actual DOM to match.

Q2. What is the difference between declarative and imperative UI programming?

Imperative code describes the exact steps to reach a result (manually manipulating the DOM). Declarative code describes the desired end result for a given state, and lets the framework figure out how to get there — the approach React embraces.

Q3. Is React a full framework?

IntermediateLearn topic →

No — React is a UI library. Routing, data-fetching conventions, and build tooling come from separate libraries or frameworks (like React Router or Next.js) built around it.

React Setup

Q4. What tool is commonly recommended to quickly start a new plain React project?

Vite — it offers a fast dev server and build setup with minimal configuration for client-only React apps.

Q5. What does createRoot(...).render(<App />) do?

It attaches React to a DOM node (typically a single root <div>) and renders the given component tree into it — the entry point that starts a React app.

Q6. What is <StrictMode> used for?

IntermediateLearn topic →

A development-only wrapper that helps surface common mistakes, by intentionally double-invoking certain functions and warning about deprecated patterns. It has no effect on production builds.

JSX

Q7. What does JSX compile down to?

Regular JavaScript function calls, like React.createElement(type, props, children) — browsers never see JSX directly; a build tool transforms it before the code runs.

Q8. Why is className used instead of class in JSX?

Because JSX attributes ultimately become JavaScript object properties passed to createElement, and class is a reserved word in JavaScript, so React uses className instead.

Q9. Why must a component return a single root element (or a Fragment)?

IntermediateLearn topic →

JSX compiles to a single function call tree, so a component can only return one root node. A Fragment (<>...</>) lets you return multiple sibling elements without adding an extra, meaningless DOM node.

Components & Props

Q10. What must every component’s name start with, and why?

A capital letter — this is how React (and JSX) distinguishes a custom component (<MyComponent />) from a built-in HTML tag (<div />).

Q11. Can a component modify the props it receives?

No — props are read-only. Data flows one way, from parent to child; a child that needs to trigger a change should call a callback function passed down as a prop instead.

Q12. What is the special children prop?

IntermediateLearn topic →

It automatically contains whatever JSX is nested between a component’s opening and closing tags, letting a component wrap and render arbitrary content passed by its parent.

Rendering Lists & Keys

Q13. What is the purpose of the key prop when rendering a list?

It helps React identify which items changed, were added, or were removed between renders, so it can update the DOM and preserve state correctly for the right items.

Q14. Why is using the array index as a key considered risky?

IntermediateLearn topic →

If the list is reordered, filtered, or has items inserted/removed, index-based keys can cause React to associate state with the wrong item, since the index no longer reliably identifies the same logical item across renders.

Q15. Is a key passed down to the child component as a regular prop?

No — key is a special value used internally by React for reconciliation, and is never accessible as props.key inside the component.

Conditional Rendering

Q16. How does React handle conditional rendering?

Through plain JavaScript — if statements, ternary expressions, and logical operators — since JSX is just an expression returned from a function, not a special templating syntax.

Q17. What is a common bug with {count && <Component />} when count is 0?

IntermediateLearn topic →

Since 0 is falsy but still a valid, renderable value, React renders the literal "0" on screen instead of nothing. Using a comparison like count > 0 avoids this.

Q18. What happens when a component returns null?

Nothing is rendered for that component — it’s a valid way to conditionally render "no UI" at all.

Handling Events

Q19. What is wrong with writing onClick={handleClick()} instead of onClick={handleClick}?

The version with parentheses calls handleClick immediately during render and passes its return value as the handler, instead of passing a reference to the function to be called later on click.

Q20. How do you pass an argument to an event handler?

By wrapping the call in an inline arrow function, e.g. onClick={() => handleClick(id)}, so the function is only invoked when the event actually fires.

Q21. What does event.preventDefault() commonly stop?

IntermediateLearn topic →

A browser’s default action for that event — most commonly, preventing a form submission from triggering a full page reload.

useState & State

Q22. What does useState(initialValue) return?

An array with exactly two items: the current state value, and a setter function used to update it and trigger a re-render.

Q23. Does calling a state setter update the variable immediately?

IntermediateLearn topic →

No — it schedules a re-render for the next render cycle. Reading the state variable immediately after calling its setter still shows the old value from the current render.

Q24. Why should you use the functional update form, setCount(prev => prev + 1), for sequential updates?

It guarantees each update reads the latest state value, even when several updates are queued together — using the plain value form (setCount(count + 1)) repeatedly can incorrectly reuse the same stale value.

Forms & Controlled Inputs

Q25. What makes an input "controlled"?

Its value is driven entirely by React state rather than the DOM’s own internal state — the value comes from a state variable, and onChange updates that state on every keystroke.

Q26. Which attribute does a controlled checkbox use instead of value?

checked, paired with an onChange handler reading event.target.checked.

Q27. What is the advantage of managing multiple form fields with a single state object instead of one useState call per field?

IntermediateLearn topic →

It reduces boilerplate for forms with many fields, and each change handler can update just the changed key using the input’s name attribute and a spread update.

Component Composition

Q28. What is "prop drilling"?

IntermediateLearn topic →

Passing a prop down through several intermediate components that don’t use it themselves, purely to reach a deeply nested child that does.

Q29. How can a component accept more than one distinct content area, beyond just children?

IntermediateLearn topic →

By accepting JSX through regular named props (like left and right), effectively creating multiple "slots" a parent can fill.

Q30. What is one benefit of favoring composition over one large, heavily-configured component?

IntermediateLearn topic →

It avoids threading props through components that don’t actually need them, and keeps each component focused on a single responsibility.

Styling in React

Q31. What is the main advantage of CSS Modules over a plain imported CSS file?

IntermediateLearn topic →

Class names are automatically scoped to the component that imports them, avoiding naming collisions with identically-named classes used elsewhere in the app.

Q32. What type of value does the style prop expect?

A JavaScript object with camelCase property names (e.g. { backgroundColor: "red" }), not a CSS string.

Q33. Why are inline styles a poor fit for hover effects and media queries?

IntermediateLearn topic →

The style prop only sets static inline CSS properties and has no way to express pseudo-classes (:hover) or @media rules.

Fragments & Portals

Q34. What problem does a Fragment solve?

It lets a component return multiple sibling elements without adding an extra, meaningless wrapping DOM node — useful when an extra <div> would break CSS layouts like Flexbox or Grid.

Q35. When do you need the full <Fragment key={...}> form instead of the <>...</> shorthand?

IntermediateLearn topic →

Whenever the Fragment needs a key — for example, when a Fragment is returned inside a .map() over a list — since the shorthand syntax cannot accept attributes.

Q36. Why are portals commonly used for modals?

They render content into a different DOM node (often near the end of <body>), letting it visually escape an ancestor’s overflow: hidden or z-index stacking context, while events still bubble through the React tree normally.

useEffect & Side Effects

Q37. What does an empty dependency array [] mean for useEffect?

The effect runs exactly once, after the component’s first render — equivalent in spirit to componentDidMount in class components.

Q38. What does a function returned from useEffect do?

IntermediateLearn topic →

It acts as a cleanup function, called by React right before the effect runs again (if dependencies changed) and once more when the component unmounts.

Q39. Why is omitting a used value from the dependency array risky?

The effect can end up reading a stale, outdated value captured from an earlier render instead of the current one, since the effect only re-runs when a listed dependency changes.

Component Lifecycle

Q40. What are the three phases of a component’s lifecycle?

Mounting (first render), updating (re-rendering due to new props/state/context), and unmounting (removed from the DOM).

Q41. Which useEffect pattern corresponds to componentDidMount?

IntermediateLearn topic →

useEffect(() => { ... }, []) — an effect with an empty dependency array runs only once, after the first render.

Q42. What is one advantage of useEffect over separate class lifecycle methods?

Setup and cleanup logic for the same concern can live together in one function, instead of being split across componentDidMount and componentWillUnmount.

Lifting State Up

Q43. What does "lifting state up" mean?

Moving shared state to the closest common ancestor of the components that need it, then passing it back down as props to each of them.

Q44. How does a child request a change to state that now lives in its parent?

IntermediateLearn topic →

Through a callback function passed down as a prop, which the child calls — the parent then updates its own state, and the new value flows back down through props.

Q45. What is a sign that lifting state up is no longer the best solution?

When the shared state needs to reach components many levels apart, forcing props to thread through several unrelated intermediate components — often a sign to reach for Context instead.

Context API

Q46. What problem does the Context API solve?

Sharing data across a component tree — like theme, locale, or the logged-in user — without manually threading props through every intermediate component (prop drilling).

Q47. Which hook reads a context’s current value inside a component?

useContext(SomeContext).

Q48. What happens to a context’s consumers when its Provider value changes?

Every component consuming that context re-renders, even if it only uses part of the value — a key limitation to keep in mind for frequently-changing, performance-sensitive state.

useRef & Refs

Q49. Does updating a ref’s .current value trigger a re-render?

No — unlike state, mutating a ref does not cause the component to re-render.

Q50. What is the most common use of a ref attached to a JSX element?

Getting direct access to the underlying DOM node — for example, to call .focus() on an input, something not achievable purely declaratively through props.

Q51. When should you avoid reading or writing a ref?

During the component’s render body — refs should only be read or written inside event handlers or effects, since accessing them during rendering makes the render unpredictable.

Custom Hooks

Q52. What naming convention must a custom hook follow?

Its name must start with "use" — this tells React and linting tools (like eslint-plugin-react-hooks) that it follows the Rules of Hooks.

Q53. Do two components calling the same custom hook share state?

IntermediateLearn topic →

No — each call to the hook creates its own completely independent copy of the internal state. Only the logic is reused, not the data.

Q54. What is the difference between reusing logic with a custom hook and reusing UI with a component?

A custom hook shares stateful behavior (state and side effects), while a component shares rendered JSX markup — they solve different problems and are frequently combined.

Hooks Overview

Q55. What must every hook’s name start with?

"use" — this convention is how React and linters (eslint-plugin-react-hooks) recognize a function as a hook subject to the Rules of Hooks.

Q56. What are the two Rules of Hooks?

IntermediateLearn topic →

Only call hooks at the top level (never inside loops, conditions, or nested functions), and only call hooks from React function components or other custom hooks.

Q57. Why must hooks be called in the same order on every render?

React matches each hook call to its internal state by the order it was called in, not by name — calling hooks conditionally would shift that order between renders and corrupt the association between hook calls and their state.

useLayoutEffect

Q58. What is the key timing difference between useEffect and useLayoutEffect?

IntermediateLearn topic →

useLayoutEffect fires synchronously immediately after DOM mutations but before the browser paints, while useEffect fires asynchronously after the paint has already happened.

Q59. What problem does useLayoutEffect solve that useEffect cannot?

It prevents visible flicker when a component needs to measure the DOM and synchronously adjust layout based on that measurement, since the correction happens before anything is painted.

Q60. Why should useLayoutEffect be used sparingly?

IntermediateLearn topic →

Because it runs synchronously and blocks the browser from painting until it finishes, a slow useLayoutEffect can make the whole page feel less responsive.

useImperativeHandle

Q61. What does useImperativeHandle let a component do?

IntermediateLearn topic →

Customize exactly what value is exposed when a parent component attaches a ref to it, instead of exposing the entire underlying DOM node.

Q62. Why expose a small custom API instead of the raw DOM node?

It keeps a clean boundary between the component and its parent, avoiding tight coupling to internal implementation details the parent shouldn’t need to know about.

Q63. As of React 19, is forwardRef still required to accept a ref prop?

No — function components can accept ref directly as a regular prop, though useImperativeHandle itself still works the same way regardless.

useTransition

Q64. What does startTransition let you do?

IntermediateLearn topic →

Mark a state update as low-priority, so React can keep the rest of the UI responsive and interrupt the transition if something more urgent (like further typing) comes in.

Q65. What does the isPending value returned by useTransition indicate?

That the transition is still being processed in the background, useful for showing a subtle loading indicator without blocking the rest of the UI.

Q66. What happens if a new transition starts while an older one is still processing?

React abandons the stale, in-progress transition and starts fresh with the latest value, so the UI never shows outdated results from an interrupted update.

useDeferredValue

Q67. What does useDeferredValue return?

IntermediateLearn topic →

A version of the given value that lags behind during urgent updates and catches up once React has spare rendering capacity.

Q68. How does useDeferredValue differ from a fixed-delay debounce?

It adapts to the actual device and current workload instead of waiting a fixed amount of time, which can be faster or slower than any hardcoded delay.

Q69. When is useDeferredValue generally preferred over useTransition?

When you don’t directly control the update that changes a value — for example, when an expensive component is fed by a fast-changing prop rather than a state update you trigger yourself.

useId

Q70. What problem does useId solve?

Generating unique, SSR-safe IDs for accessibility attributes (like label/input pairs) that stay consistent across multiple instances of the same component on a page.

Q71. Why is Math.random() unsafe for generating an element’s id?

IntermediateLearn topic →

It produces a different value on the server than on the client, causing a hydration mismatch — exactly the class of bug useId is designed to avoid.

Q72. Should useId be used to generate keys for a rendered list?

IntermediateLearn topic →

No — list keys should come from the data itself; useId is meant for generating a component instance’s own accessibility-related IDs.

useSyncExternalStore

Q73. What kind of data source is useSyncExternalStore designed for?

State that lives outside of React entirely — a browser API, a custom event emitter, or a third-party store — rather than state already managed with useState or useReducer.

Q74. What do the subscribe and getSnapshot arguments do?

subscribe registers a callback to be notified of store changes (returning an unsubscribe function), and getSnapshot returns the store’s current value.

Q75. Why is useSyncExternalStore preferred over a manual useEffect + useState subscription?

It guarantees a consistent, non-stale value even under React’s concurrent rendering, which a manual effect-based subscription can’t fully guarantee.

useDebugValue

Q76. What does useDebugValue affect?

Only how a custom hook’s value is labeled in React DevTools — it has no effect on the component’s actual behavior or rendered output.

Q77. Why is useDebugValue mainly useful for custom hooks specifically?

IntermediateLearn topic →

Built-in hooks like useState already display their value in DevTools, while a custom hook’s internal state would otherwise appear unlabeled and opaque.

Q78. What does the optional formatting function argument to useDebugValue do?

It defers expensive formatting so it only runs when DevTools is actively inspecting that hook, avoiding wasted work during normal rendering.

The use() Hook

Q79. What is unique about use() compared to hooks like useState?

It can be called conditionally and inside loops, unlike every other hook, which must always be called unconditionally at the top level.

Q80. What happens when use() is passed a Promise?

It suspends the component until the Promise resolves, integrating directly with Suspense without needing manually-managed loading state.

Q81. Can use() read a Context value?

Yes — it can read Context similarly to useContext, but with the added ability to do so conditionally, which useContext cannot.

useOptimistic

Q82. What does useOptimistic let you do?

IntermediateLearn topic →

Show an expected result immediately in the UI before an async action actually finishes, making interactions like likes or sending a message feel instant.

Q83. What happens automatically if the underlying async action fails?

React reverts to the real state that was passed into useOptimistic, with no manual rollback code required.

Q84. What kind of actions are the best fit for useOptimistic?

Actions that succeed the vast majority of the time — for actions with a meaningfully high failure rate, a visible loading state may communicate uncertainty more honestly.

useActionState

Q85. What does useActionState track automatically for a form Action?

IntermediateLearn topic →

Both the action’s current result/state (like a validation error or success message) and a pending flag, without separate useState calls for each.

Q86. What arguments does the function passed to useActionState receive?

The previous state and the submitted form data.

Q87. What is the main benefit of useActionState over manually wiring useState for pending/result state?

It consolidates a very common cluster of form-handling boilerplate — pending tracking and result/error state — into a single hook tied directly to the action.

useFormStatus

Q88. What does useFormStatus let a component read?

IntermediateLearn topic →

The submission status of the nearest parent <form>, from a component rendered inside it — with no props needed.

Q89. What happens if useFormStatus is called in the same component that renders the form itself?

It always returns the default, non-pending status — a form cannot read its own status through this hook; it must be called from a component nested inside the form.

Q90. What problem does useFormStatus solve compared to manually passing a pending prop down?

It avoids prop drilling an isPending value down to nested components like a reusable submit button, which can instead read the form’s status directly.

useReducer

Q91. What two values does useReducer return?

The current state and a dispatch function used to send actions describing what happened.

Q92. What does a reducer function receive as arguments?

IntermediateLearn topic →

The current state and an action object (typically with a type and optional payload) describing the update that should happen.

Q93. When is useReducer generally preferred over useState?

When state updates are complex and depend on several related sub-values at once — centralizing the update logic in one reducer function keeps it easier to follow and test than scattering it across many event handlers.

useMemo & useCallback

Q94. What does useMemo do?

IntermediateLearn topic →

It re-runs an expensive calculation only when one of its listed dependencies changes, reusing the cached result on every other render.

Q95. What does useCallback memoize?

IntermediateLearn topic →

A function reference — returning the same function instance across renders as long as its dependencies haven’t changed, instead of creating a brand-new function every render.

Q96. Why is useCallback often paired with React.memo?

Without a stable function reference, a newly-created function prop on every parent render defeats React.memo’s shallow prop comparison, causing the memoized child to re-render anyway.

Error Boundaries

Q97. What does an error boundary do?

IntermediateLearn topic →

It catches JavaScript errors thrown during rendering in its child component tree, and shows a fallback UI instead of letting the error crash the entire app.

Q98. Can an error boundary currently be written as a function component?

No — it must be a class component, since getDerivedStateFromError and componentDidCatch have no direct function-component/hook equivalent yet.

Q99. Does an error boundary catch an error thrown inside an onClick handler?

No — error boundaries only catch errors during rendering, in lifecycle methods, and in constructors. Errors in event handlers or async code need to be handled separately, typically with try/catch.

React Router

Q100. What does the Link component do differently from a regular <a> tag?

It navigates client-side, updating the URL and swapping the rendered route without triggering a full page reload.

Q101. Which hook reads a dynamic route parameter like :userId?

IntermediateLearn topic →

useParams(), which returns an object of the current route’s parameters.

Q102. How does file-based routing (used by frameworks like Next.js) differ from React Router’s declarative <Route> elements?

File-based routing derives the URL structure automatically from the folder/file structure of the project, rather than requiring routes to be explicitly declared with <Route> components.

Performance Optimization

Q103. What does React.memo do?

IntermediateLearn topic →

It wraps a component so it skips re-rendering when its props haven’t changed (via a shallow comparison), even if its parent re-renders.

Q104. Why can React.memo fail to prevent a re-render even when the "real" data hasn’t changed?

If a prop is a newly-created object, array, or function on every parent render, the shallow comparison always sees it as different — which is why React.memo is often paired with useMemo/useCallback.

Q105. What is the purpose of list virtualization?

To render only the items currently visible in the viewport for a very long list, recycling DOM nodes as the user scrolls, instead of rendering every item at once.

Suspense & Lazy Loading

Q106. What does the fallback prop on <Suspense> do?

It renders temporary UI shown while the content wrapped inside the Suspense boundary is still loading (e.g. a lazy component still downloading, or data still resolving).

Q107. What must a component created with React.lazy be rendered inside?

IntermediateLearn topic →

A Suspense boundary, which shows its fallback while the component’s code chunk is downloading.

Q108. Does Suspense handle errors, like a failed lazy import?

No — Suspense only handles the "still loading" state. Errors need to be handled by an error boundary, which is commonly used alongside Suspense.

Server vs Client Components

Q109. Where does a Server Component run?

IntermediateLearn topic →

On the server only — its code never ships to the browser, and it cannot use hooks like useState or useEffect.

Q110. What directive marks a file as containing Client Components?

"use client" at the top of the file.

Q111. Can a Client Component directly import and render a Server Component?

No — data and rendered output flow from server to client, not the reverse. A Server Component can render a Client Component as a child, passing serializable props, but not vice versa.

Data Fetching Patterns

Q112. Why does a manual useEffect-based fetch often track a "cancelled" flag?

To prevent a race condition — if a dependency (like an id) changes quickly, an older, slower request could resolve after a newer one and incorrectly overwrite fresh data with stale data.

Q113. What does a library like TanStack Query add over manual fetching with useEffect?

IntermediateLearn topic →

Automatic caching by key, request deduplication, background refetching, and built-in race condition handling — removing the need to hand-write that logic in every component.

Q114. How can a Server Component fetch data differently from a Client Component?

It can fetch data directly with async/await during rendering, with no client-side request or loading state needed for that initial render.

Testing React Components

Q115. What does React Testing Library encourage testing?

Behavior from the user’s perspective — what’s rendered on screen and how it responds to interaction — rather than internal implementation details like component state.

Q116. Which query is generally preferred for finding elements in a test?

IntermediateLearn topic →

getByRole, since it also verifies the element is genuinely accessible (a real button, heading, etc.), unlike getByTestId which relies on an artificial attribute.

Q117. Why use findByRole instead of getByRole for content that appears asynchronously?

findBy* queries return a promise and wait for the element to appear, while getBy* throws immediately if the element isn’t present yet — essential for testing components that fetch data or update after a delay.

React 19 Features

Q118. What is unique about the use() hook compared to other hooks?

It can be called conditionally, unlike other hooks which must always run unconditionally at the top level — and it can read a Promise, suspending the component until it resolves.

Q119. What does useActionState provide beyond a plain async function?

Built-in tracking of pending state and the action’s result/error, without manually wiring separate useState calls for each of those concerns.

Q120. What does useOptimistic do?

It shows an expected result immediately in the UI before an async action actually finishes, automatically reverting to the real value if the action fails.

State Management Libraries

Q121. What problem does a dedicated state management library like Redux or Zustand typically solve?

IntermediateLearn topic →

Managing large, frequently-updated, widely-shared application state more efficiently than Context alone, which re-renders every consumer on any change.

Q122. How does server state (API data) differ from client UI state?

Server state needs caching, refetching, and staleness handling — concerns that libraries like TanStack Query specialize in, separately from tools focused on purely client-side UI state.

Q123. Should every new React project start with a state management library like Redux?

IntermediateLearn topic →

No — many apps are well served by useState, useReducer, and Context alone; a dedicated library is worth adding once prop drilling or Context re-renders become an actual, measured problem.

React Best Practices

Q124. Why avoid storing a value in state if it can be computed from existing props/state?

IntermediateLearn topic →

A separately-stored derived value can get out of sync with the values it depends on. Computing it fresh during render guarantees it’s always correct.

Q125. What three states should most components that depend on async data handle explicitly?

IntermediateLearn topic →

Loading, error, and empty — beyond the "happy path with data," these are the states real-world conditions (slow networks, failed requests, no results) actually produce.

Q126. What is a common sign that a useEffect is unnecessary?

When it exists only to react to a state change that was already caused by your own event handler — that logic usually belongs directly in the event handler instead of a separate effect.