React Interview Questions and Answers

React interview questions and answers in 2026 go well past "what is JSX?" Interviewers expect you to reason about hooks as synchronization, when useMemo helps vs hurts, how Server Components change data fetching, and how you would build a search bar or todo list under time pressure. React JS interview questions and answers loops at product companies blend fundamentals, architecture judgment, and React coding interview questions—live components, state fixes, and performance debugging.

Below are 40+ React interview questions covering fundamentals, hooks, state, performance, React 19.2, and live coding scenarios. Technical sections include a strong answer sample you can say aloud. This article owns beginner and mid fundamentals — JSX, props/state, hooks, forms, lists/keys, routing, testing, and React 19.2 topics including useEffectEvent and <Activity />. For scenario-based senior prep (Fiber, concurrency, React Compiler, RSC architecture, hydration, performance profiling, and production scenarios), see interview questions on React JS for experienced developers.

NOTE
Prep target: Know hooks cold, then practice coding—controlled form, debounced search, list with keys, and explaining why an effect re-runs. Senior loops add React 19 Actions, TanStack Query, and rendering trade-offs without premature optimization.

Interview context and how to prepare

What React interviews actually test

React interviews test whether you can build interactive UIs that stay correct as state and data change—not whether you memorized every API from 2018.

Layer What interviewers probe
Fundamentals Components, JSX, props, state, one-way data flow
Hooks useState, useEffect, dependencies, custom hooks
Rendering Reconciliation, keys, memoization judgment
State & data Local vs server state, Context, TanStack Query
Performance Re-render causes, useMemo/useCallback, code splitting
Modern React Suspense, transitions, RSC, React 19 Actions
Coding Small components live—forms, lists, fetch patterns
Level Emphasis
Junior Hooks basics, props, simple lists/forms
Mid Effects, routing, testing, API integration
Senior Architecture, performance, RSC, accessibility, system trade-offs

Coding rounds vs theory rounds

Theory rounds ask definitions—Virtual DOM, lifecycle in a hooks world, controlled inputs.

Coding rounds ask you to ship in 30–45 minutes:

Common exercise What they watch
Todo / filter list State shape, keys, immutability
Search with debounce Effects, cleanup, stale closures
Fetch and display Loading/error, abort, query library mention
Form validation Controlled fields, submit handling
Fix a buggy component Missing deps, mutating state, wrong key

Strong candidates think aloud, state assumptions, and write tests or edge-case handling when time allows.

A typical React interview loop

Round Duration Focus
Recruiter / HM 30 min Projects, stack, team UI standards
React deep dive 45–60 min Hooks, rendering, state architecture
Live coding 45–90 min Component exercise, debug session
System design (senior) 45 min Frontend architecture, data layer, perf
Behavioral 30 min Collaboration, incidents, code review

Take-home UIs often include README trade-offs and test coverage—not only pixels.

A realistic 4–6 week React prep plan

Week Focus Output
1 Core React — JSX, props, state, lists, forms Rebuild todo without tutorial
2 Hooks depth — effects, refs, custom hooks useDebounce, useFetch patterns
3 Data — TanStack Query, error boundaries List page with loading/error/empty
4 Performance & testing — RTL, memo judgment Fix one unnecessary re-render case
5 React 18/19 — Suspense, transitions, RSC basics Explain client vs server component split
6 Coding drills + mock 3 timed exercises; 2 STAR stories

Build one small app (dashboard, catalog, or admin table) you can demo and defend.


React fundamentals

What is React and why use it?

What interviewers are testing: Whether you understand React's declarative, component-based model and can explain what React provides versus what a framework such as Next.js adds.

React is a JavaScript library for building user interfaces with a component-based model and declarative rendering—you describe UI as a function of state, React updates the DOM when state changes.

Benefit Detail
Components Reusable, composable UI units
Declarative UI Less manual DOM patching
Ecosystem Routing, state, meta-frameworks (Next.js, Remix)
Talent pool Widely adopted in product companies

React is a library, not a full framework—you choose routing, data layer, and styling.

A strong answer is:

React lets teams compose UIs from components with predictable one-way data flow; I use it when rich client interactivity and a large ecosystem matter more than a batteries-included monolith framework.

What is JSX?

What interviewers are testing: Whether you can explain JSX as compile-time syntax sugar, automatic vs classic transforms, and why it is not HTML.

JSX is syntax sugar that looks like HTML inside JavaScript. Build tools transform it into JavaScript calls understood by the React JSX runtime. Older tooling used explicit React.createElement() calls; modern projects normally use the automatic JSX transform, so importing React solely for createElement is no longer required.

jsx
function Greeting({ name }) {
  return <h1>Hello, {name}</h1>;
}

Rules interviewers mention:

  • One parent element or Fragment (<>...</>)
  • className instead of class
  • JavaScript expressions in {curly braces}
  • Self-closing tags required (<img />)

JSX is not HTML—attributes and casing follow React conventions.

A strong answer is:

JSX is declarative syntax compiled to JavaScript function calls—it keeps UI structure readable while staying in the JavaScript type and tooling world.

What is the Virtual DOM and how does reconciliation work?

What interviewers are testing: Whether you can explain reconciliation and Fiber without overstating React as always computing the smallest possible DOM patch set.

React keeps a lightweight tree representing UI. On state change:

  1. React calls your component functions to produce a new element tree
  2. Diffs new tree vs previous (reconciliation)
  3. React reconciles the new element tree against the previous tree and commits the necessary host/DOM changes

Fiber (React 16+) enables incremental work, priorities, and concurrent rendering—reconciliation can pause and resume.

Concept Interview point
Not magic speed Large lists still need stable keys and intentional memoization
Keys Help match list items across renders
Batched updates React 18 expanded automatic batching beyond React event handlers to updates from sources such as promises and timers when using the modern root API

A strong answer is:

React builds a new element tree each render, reconciles it against the previous tree, and commits the necessary DOM changes—keys and structure determine whether list updates stay efficient.

What is the difference between props and state?

What interviewers are testing: whether you treat props as read-only parent input and state as component-owned data that triggers re-renders.

Props State
Source Parent passes down Owned inside component (or hook)
Mutability Read-only for child Updated via setter (setState, useState)
Purpose Configuration, callbacks UI that changes over time

One-way data flow: parent state → child props → events call parent setters.

Anti-pattern: child mutates props object directly.

A strong answer is:

Props are inputs from parents; state is local mutable UI data updated immutably through setters—data flows down, events flow up.

Controlled vs uncontrolled components?

What interviewers are testing: whether you choose controlled inputs when React must own form state and uncontrolled refs for simple file or legacy integrations.

Type Who owns input value
Controlled React state drives value + onChange
Uncontrolled DOM holds value; read via ref
jsx
// Controlled
const [email, setEmail] = useState("");
<input value={email} onChange={(e) => setEmail(e.target.value)} />

// Uncontrolled
const inputRef = useRef(null);
<input ref={inputRef} defaultValue="" />

Prefer controlled for validation, instant feedback, and predictable tests. Uncontrolled fits simple forms or file inputs.

A strong answer is:

Controlled inputs bind value to state for validation and single source of truth; uncontrolled defer to the DOM and refs when that is simpler.


Hooks and component behavior

Explain useState — how does React schedule updates?

What interviewers are testing: Whether you understand state as a render snapshot, batching, and when functional updates are required.

useState returns [value, setter]. Updates are scheduled—React may batch multiple setters in one render.

jsx
const [count, setCount] = useState(0);

function increment() {
  setCount((c) => c + 1); // functional update — safe when next state depends on previous
}
Pattern When
setCount(5) Absolute new value
setCount(c => c + 1) Depends on previous state
Lazy init useState(() => expensive()) Heavy initial computation once

Calling the setter schedules another render; it does not change the state variable captured by the currently executing render.

A strong answer is:

useState gives each render a snapshot of local state. I use functional updates when the next state depends on the previous value, especially when updates may be batched.

Explain useEffect — dependencies, cleanup, and pitfalls.

What interviewers are testing: whether you model effect dependencies, cleanup, and stale-closure pitfalls—not just when effects run.

useEffect synchronizes your component with external systems—fetch, subscriptions, DOM APIs—not "lifecycle replacement" only.

jsx
useEffect(() => {
  const controller = new AbortController();
  fetch(url, { signal: controller.signal })
    .then((r) => r.json())
    .then(setData)
    .catch((error) => {
      if (error.name !== "AbortError") {
        handleError(error);
      }
    });
  return () => controller.abort(); // cleanup on dep change or unmount
}, [url]);
Pitfall Fix
Missing deps Include values used inside; or move stable logic out
Stale closure in effects useEffectEvent for event-like logic that should see latest props/state without becoming a reactive dependency—or correct deps, not lint silencing
No cleanup Leaks timers/subscriptions
Strict Mode double invoke (dev) Effects must be idempotent; cleanup must work

Prefer TanStack Query or framework data loaders over raw fetch effects for server data in 2026 interviews. In React 19.2, useEffectEvent separates event-like logic inside Effects from reactive dependencies—useful when an Effect should see the latest values without re-synchronizing for those values. Do not use it merely to silence dependency lint errors. Effect Events can only be called from Effects or other Effect Events—do not pass them to child components or call them from regular event handlers.

A strong answer is:

useEffect runs after React commits the update. I declare honest dependencies, clean up subscriptions and abort fetches, and use useEffectEvent in React 19.2 when Effect-triggered logic needs the latest props/state without becoming a dependency. I reach for query libraries instead of hand-rolled fetch effects when data is server-backed.

What are the Rules of Hooks?

What interviewers are testing: Whether you know why hook call order matters and when the React 19 use() API is an exception.

  1. Only call hooks at the top level — not inside loops, conditions, or nested functions
  2. Only call hooks from React functions — components or custom hooks

Why: React relies on call order to associate state with each hook instance.

React 19 exception: use() is a React API rather than a normal Hook. It may be called conditionally or in loops, although it still must be called while React renders a component or Hook.

Breaking rules causes "Rendered more hooks than previous render" bugs—impossible to debug casually.

Custom hooks must also follow these rules and name with use prefix.

A strong answer is:

Hooks run in a fixed order every render—I never call them conditionally except for use(), which React documents as a special API, and I extract reusable logic into custom hooks instead of copying stateful patterns.

When do useCallback and useMemo help — and when are they premature optimization?

What interviewers are testing: Whether you justify memoization with measured re-render cost—not blanket useCallback on every handler.

Hook Caches
useMemo Expensive computation result
useCallback Stable function reference

Helpful when:

  • Passing callbacks to React.memo children that would re-render on reference change
  • Heavy derived data (large list filtering) proven slow in profiler

Not needed for every inline function—manual memoization has complexity and runtime overhead of its own, so it should solve an actual identity or computation problem.

jsx
const visible = useMemo(() => items.filter((i) => i.active), [items]);
const onSelect = useCallback((id) => setSelected(id), []);

Interview trap: wrapping everything in useCallback without memoized children buys nothing.

The React Compiler can automatically memoize values, functions, and components where safe, reducing routine manual useMemo/useCallback/memo. Understand them anyway because existing codebases and library boundaries still rely on them—do not mechanically add manual memoization when the compiler/toolchain already handles it.

A strong answer is:

I use useMemo and useCallback when profiling shows wasted child renders or expensive derivations—not by default on every handler.

What is useRef used for?

What interviewers are testing: Whether you distinguish mutable non-rendering state from UI state and know when refs are appropriate for DOM access or imperative integration.

useRef holds a mutable box that persists across renders without triggering re-render when .current changes.

Use Example
DOM access Focus input, measure element
Mutable imperative value Timer ID, third-party instance
Latest-value escape hatch Occasionally needed for imperative callbacks; prefer useEffectEvent for Effect Events
jsx
const inputRef = useRef(null);
useEffect(() => inputRef.current?.focus(), []);

Unlike state, updating ref.current does not schedule render.

A strong answer is:

I use refs for DOM nodes and mutable values that should survive renders without causing a render. If the value belongs in visible UI, it should normally be state instead.

When should you use useContext?

What interviewers are testing: Whether you know when Context subscriptions become too broad and how to split or memoize provider values.

Context shares values deep in the tree without prop drilling—theme, locale, auth snapshot.

Good fit Poor fit
Low-frequency updates Frequently changing context values can cause broad updates across subscribed consumers, especially when one large context combines unrelated state
Theme, i18n, auth user Entire app state store

Pattern:

jsx
const ThemeContext = createContext("light");

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

For complex client state, consider Zustand, Redux Toolkit, or colocated state + query library.

A strong answer is:

A provider value change updates components subscribed to that context, so I avoid one large frequently changing context and split concerns when needed.

What are custom hooks? Implement a useDebounce pattern.

What interviewers are testing: Whether you can implement a real custom Hook—not only a standalone debounce utility—and explain how it composes with effects.

Custom hooks extract stateful logic reusable across components—they must follow Rules of Hooks.

jsx
function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => clearTimeout(timer);
  }, [value, delay]);

  return debouncedValue;
}

// Usage
const debouncedQuery = useDebounce(query, 300);

Pair debounced values with fetch effects or query libraries—cleanup clears the timeout on unmount or when value changes.

A strong answer is:

Custom hooks share stateful behavior—I extract debounce, fetch, and media-query logic into use* functions so components stay declarative.


State management and data fetching

Local state vs global state vs server state?

What interviewers are testing: whether you keep UI state local, lift only when siblings need it, and put server cache in TanStack Query—not Redux by default.

Category Examples Tooling
Local Form field, modal open useState
Shared client Wizard steps, UI preferences Context, Zustand, Redux
Server API records, pagination TanStack Query, SWR, RSC

Colocation principle: keep state as low as possible until multiple distant components need it.

Server state is async, cached, and shared—different from client UI toggles. Do not copy server lists into Redux by default in 2026 greenfield apps.

A strong answer is:

Local state for UI, global client libraries only when prop drilling hurts, and dedicated server-state tools for API data with cache and invalidation.

Why use TanStack Query instead of useEffect for fetching?

What interviewers are testing: Whether you justify TanStack Query for server-state caching and when raw useEffect fetch is still appropriate.

useEffect fetch TanStack Query
Manual loading/error flags Built-in states
No cache deduplication Shared cache per query key
Refetch logic reinvented Stale time, retry, invalidation
Race conditions manual Query-key-based cache sharing and request deduplication
jsx
const { data, isLoading, error } = useQuery({
  queryKey: ["orders", page],
  queryFn: () => fetchOrders(page),
});

Interviewers want you to mention query keys, stale-while-revalidate, and mutations with optimistic updates. TanStack Query is not mandatory for every fetch—the decision depends on server-state complexity and framework architecture.

A strong answer is:

TanStack Query handles caching, deduplication, and refetch policies for server state—I use effects for true externals like subscriptions, not routine GET requests.

When is Redux Toolkit still justified?

What interviewers are testing: Whether you know when shared client state complexity justifies Redux Toolkit over lighter stores and query libraries.

Redux shines when:

  • Many features read/write shared client state with traceable updates
  • You need devtools, time-travel debugging, middleware
  • Complex cross-feature workflows (multi-step wizards, offline sync)

Often overkill for apps where server state dominates—Query + light Context/Zustand covers many products.

Redux Toolkit reduces boilerplate with slices and createAsyncThunk—know it even if you prefer simpler stores.

A strong answer is:

I reach for Redux when client state is complex and many modules need predictable updates; otherwise Query plus minimal local/global state is enough.

What is lifting state up?

What interviewers are testing: Whether you know when to lift shared state to a common ancestor versus URL or store patterns.

When two siblings need the same data, move state to their common parent and pass props down + callbacks up.

text
Parent (owns `filter`)
       /      \
   List      FilterBar

Alternative: shared store or URL search params for bookmarkable filter state.

A strong answer is:

I lift state to the lowest common ancestor when siblings must stay in sync, or use URL/query state when users should share or bookmark it.

Composition vs inheritance in React?

What interviewers are testing: Whether you favor composition—children, render props, and hooks—over class inheritance for reuse.

React favors composition—pass children or render props instead of deep class hierarchies.

jsx
function Card({ title, children }) {
  return (
    <section>
      <h2>{title}</h2>
      {children}
    </section>
  );
}

Patterns: compound components, slots, higher-order components (less common now), custom hooks (preferred reuse in hooks era).

A strong answer is:

I compose behavior with children and hooks rather than subclassing components—composition keeps trees flexible and types clearer.


Performance, rendering, and lists

What does React.memo do?

What interviewers are testing: Whether you understand prop comparison and can justify memoization based on measured render cost rather than applying it everywhere.

React.memo wraps a component to skip re-render when each prop compares equal to its previous value using Object.is, unless a custom comparator is supplied.

memo only optimizes re-renders caused by unchanged parent props; the component still renders when its own state or a Context it consumes changes.

Requires stable props—inline object/function props defeat memo unless parent uses useMemo/useCallback.

Use when profiler shows expensive pure presentational children re-rendering often.

A strong answer is:

React.memo skips re-render when props are unchanged by Object.is—I pair it with stable callbacks only after profiling proves child render cost matters.

Why are keys important in lists?

What interviewers are testing: whether you use stable unique keys so React reconciles lists without remounting or state loss.

Keys help React identify which items changed, were added, or removed.

Key choice Result
Stable unique id Correct reuse of component state
Array index Breaks on reorder/insert—avoid when list mutates

Wrong keys cause state bugs (wrong row stays checked) and inefficient DOM updates.

A key must be stable and unique among its siblings—it does not need to be globally unique across the application.

A strong answer is:

Keys must be stable per entity— I use database ids, not array indexes, for dynamic lists so React matches the right row across renders.

What causes unnecessary re-renders and how do you debug them?

What interviewers are testing: Whether you can trace re-render causes to state placement, context, and unstable identities at memo or effect boundaries.

Common causes:

Cause Fix
Parent re-rendered memo, split state down
Unstable object/function identity Matters at memo/effect boundaries; simplify props or stabilize only when needed
Context value recreated Memoize provider value
Global store too coarse Selectors, split contexts

Tools: React DevTools Profiler, why-did-you-render (dev), logging render counts.

A strong answer is:

I profile first, then fix the actual source—unstable props, fat context, or state living too high—not blanket memo everywhere.

What is code splitting and lazy loading in React?

What interviewers are testing: Whether you understand bundle splitting with lazy() and when the lazy component is actually rendered—not only how to import it.

Code splitting loads JavaScript chunks on demand—smaller initial bundle.

jsx
const AdminPanel = lazy(() => import("./AdminPanel"));

function App() {
  const [showAdmin, setShowAdmin] = useState(false);

  return (
  <>
    <button onClick={() => setShowAdmin(true)}>Open admin</button>
    {showAdmin && (
      <Suspense fallback={<Spinner />}>
        <AdminPanel />
      </Suspense>
    )}
  </>
  );
}

lazy() splits the component into another bundle; actual deferral depends on when that lazy component is rendered. Route-based splitting (React Router, Next.js) is the most common production pattern.

A strong answer is:

I lazy-load heavy routes and admin surfaces behind Suspense so first paint ships only what most users need.

Why does useEffect run twice in development?

What interviewers are testing: Whether you know Strict Mode's development-only extra Effect cycle at mount and why cleanup must be correct.

React Strict Mode in development intentionally stress-tests components and effects:

  • components re-render an extra time in development
  • In development Strict Mode, React runs an extra setup→cleanup→setup cycle when an Effect mounts to expose missing cleanup bugs
  • ref callbacks are re-run with an extra setup/cleanup cycle in development

These extra checks are development-only. Normal production effects still rerun whenever their dependencies change.

Your effect cleanup must abort fetches and clear timers—double invoke proves that works.

A strong answer is:

Strict Mode stress-tests effects and cleanup in dev on purpose—I write idempotent effects with proper cleanup so production behavior stays reliable when dependencies change.


Routing, forms, errors, and testing

How does client-side routing work with React Router?

What interviewers are testing: Whether you can explain client-side routing, nested routes, and route-level data loading in modern React Router.

React Router maps URL paths to component trees without full page reload.

Concept Role
<Routes> / <Route> Path → element
<Link> Declarative navigation
useParams Dynamic segments (/users/:id)
useSearchParams Query strings
Loaders/actions Route-level data loading and mutations in data-router/framework modes

Use route guards or loaders to redirect unauthenticated users for UX, but enforce authentication and authorization again on the server/API—the client-side route guard is not a security boundary.

Pair with full stack interviews for end-to-end auth flows.

A strong answer is:

React Router keeps URL and UI in sync on the client—I use nested routes, loaders where appropriate, and guarded routes for auth.

What are error boundaries?

What interviewers are testing: Whether you know what error boundaries catch in render—and what they do not catch in events or async code.

Error boundaries catch render errors in child tree and show fallback UI—they must be class components (still in 2026) or framework equivalents.

They do not catch:

  • Event handler errors (use try/catch)
  • Async errors outside render
  • Errors in the boundary itself
jsx
class ErrorBoundary extends React.Component {
  state = { hasError: false };
  static getDerivedStateFromError() { return { hasError: true }; }
  componentDidCatch(error, info) { log(error, info); }
  render() {
    return this.state.hasError ? <Fallback /> : this.props.children;
  }
}

A strong answer is:

Error boundaries isolate render failures so the whole app does not white-screen—I log to monitoring and still handle event and async errors separately.

How do React 19 Actions improve forms?

What interviewers are testing: Whether you understand how Actions integrate async mutations with transitions—not automatic error handling for every thrown failure.

Actions are async functions passed to <form action={submitAction}> that integrate async updates with React's transition model.

Related APIs:

API Role
useActionState Action result state, dispatch, and pending status
useFormStatus Pending state in child buttons
useOptimistic Instant UI while mutation completes
jsx
function OrderForm() {
  const [state, submitAction, isPending] = useActionState(saveOrder, {
    ok: false,
  });

  return (
    <form action={submitAction}>
      {/* fields */}
      <button disabled={isPending}>Save</button>
    </form>
  );
}

async function saveOrder(prevState, formData) {
  // validate and persist
  return { ok: true };
}

A function passed directly to <form action={saveOrder}> receives formData as its single argument—the (prevState, formData) signature is for actions wired through useActionState.

Actions integrate async mutations with React's transition model. useActionState can expose action result state and pending status, useFormStatus exposes form submission status, and useOptimistic supports optimistic UI. Thrown errors still interact with error handling and boundaries.

React Actions are the broader React form/action model. "use server" belongs to frameworks/environments that support Server Functions (for example Next.js); it is not required for every React Action.

Even without Next.js, interviewers expect you to know Actions reduce hand-rolled loading flags.

A strong answer is:

React 19 Actions integrate async mutations with forms and transitions, reducing hand-rolled pending-state orchestration. I use useActionState, useFormStatus, and useOptimistic where they simplify the mutation flow.

What does <Activity /> do in React 19.2?

What interviewers are testing: Whether you understand visible vs hidden UI modes, preserved state, Effect lifecycle, and update prioritization—not as a generic layout wrapper.

<Activity /> (React 19.2) controls whether a subtree is visible or hidden:

Mode Behavior
visible Normal rendering and updates
hidden UI is hidden, state is preserved, Effects are unmounted, and updates are deprioritized

Useful for preserving navigation or tab state, pre-rendering likely next UI, or keeping expensive subtrees warm without treating them as actively visible.

A strong answer is:

<Activity /> lets me hide UI while preserving state—hidden mode unmounts Effects and deprioritizes updates, which is useful for tabs or pre-rendered panels without losing user progress.

How do you test React components?

What interviewers are testing: Whether you test behavior through accessible queries and realistic user interactions—not implementation details.

React Testing Library encourages tests that resemble user behavior:

jsx
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

test("increments counter", async () => {
  const user = userEvent.setup();
  render(<Counter />);
  await user.click(screen.getByRole("button", { name: /increment/i }));
  expect(screen.getByText("1")).toBeInTheDocument();
});

Use fireEvent only when you need lower-level event dispatch.

Layer Tool
Unit RTL + Vitest/Jest
Integration MSW for API mocks
E2E Playwright, Cypress

Test behavior and accessibility roles—not implementation details like internal state variable names.

A strong answer is:

I test what users see and do with Testing Library, mock APIs with MSW, and reserve E2E for critical flows like checkout or login.

What React accessibility practices do interviews expect?

What interviewers are testing: Whether you prioritize semantics, labels, keyboard behavior, and focus management—not ARIA alone.

Practice Detail
Semantic HTML button vs div onClick
Labels htmlFor + id on inputs
Keyboard Focus trap in modals, Escape to close
ARIA sparingly Fix semantics first
Live regions Announce async updates

React does not fix a11y automatically—see front end interviews for broader WCAG depth.

A strong answer is:

I use semantic elements, label every control, manage focus in dialogs, and test with keyboard and screen reader checks—not bolt-on ARIA only.


React 18, React 19, and Server Components

What are concurrent features in React 18?

What interviewers are testing: Whether you understand urgent vs non-urgent updates and do not put controlled text input values inside transitions.

Concurrent rendering lets React interrupt low-priority updates to keep UI responsive.

API Use
useTransition Mark non-urgent state updates (filter large list)
useDeferredValue Defer rendering expensive derived value
Suspense Wait for lazy code or async data with fallback
jsx
const [text, setText] = useState("");
const [filter, setFilter] = useState("");
const [, startTransition] = useTransition();

function handleChange(e) {
  const next = e.target.value;
  setText(next); // urgent: controls input
  startTransition(() => {
    setFilter(next); // non-urgent: expensive results
  });
}

Transitions cannot control text inputs—keep the input value in urgent state and transition downstream work.

A strong answer is:

Concurrent features prioritize urgent UI like typing over heavy re-renders—I keep controlled inputs urgent and use transitions or useDeferredValue for expensive downstream updates.

What are React Server Components (RSC)?

What interviewers are testing: Whether you understand the server/client boundary and that Client Components in the tree still ship JavaScript.

Server Components run only on the server—their implementation does not ship to the browser.

Server Component Client Component ("use client")
Component implementation stays on server Component implementation runs in browser
Can access server resources directly Can use state, browser APIs, event handlers
Adds no client JS for the Server Component itself Contributes to client bundle

Not the same as SSR: SSR still hydrates client components; RSC sends rendered output without hydrating Server Component code.

Popular in Next.js App Router—know the boundary interview answer even if your team uses Vite SPA.

A strong answer is:

Server Component code stays on the server and can access server-side data directly; interactive islands cross the boundary into Client Components and ship their own JavaScript.

What is the use() API in React 19?

What interviewers are testing: Whether you know use() is not a Hook, can be conditional, and works with framework-created Suspense-compatible Promises.

use() reads a Promise or Context during render—despite its name, it is not a Hook and can be called conditionally (unlike other hooks).

Integrates with Suspense—component suspends until Promise resolves.

jsx
function Comments({ commentsPromise }) {
  const comments = use(commentsPromise);
  return comments.map((c) => <p key={c.id}>{c.text}</p>);
}

In Client Components, do not create a new uncached Promise during render and immediately pass it to use()—framework/server-created or cached Suspense-compatible Promises are the usual pattern. use(context) can be conditional, but current React docs state reading context with use(context) is not supported in Server Components.

Prefer framework data patterns you can explain—RSC, Query, or use() with Suspense boundaries.

A strong answer is:

use() is a React API that reads promises or context during render with Suspense—it can be conditional unlike Hooks, but I rely on framework-created promises rather than ad hoc render-time fetches.

SSR vs CSR vs SSG — when do you use each?

What interviewers are testing: whether you pick SSR for SEO and first paint, CSR for highly interactive apps, and SSG for mostly static content.

Model When
CSR Dashboards behind auth, highly interactive SPA
SSR SEO pages, fast first paint with dynamic data
SSG Marketing docs, blogs with build-time content
ISR Mix—static with periodic revalidation (Next.js)

Hydration mismatch is a common production bug—server HTML must match client first render.

A strong answer is:

I pick rendering mode by SEO, personalization, and interactivity—SSG/SSR for public content, CSR or hybrid for authenticated apps with heavy client state.

What is React Compiler?

What interviewers are testing: Whether you understand what React Compiler 1.0 automates and why manual memoization knowledge still matters.

The React Compiler reached 1.0 in October 2025 and automatically memoizes components and values when safe—reducing manual useMemo/useCallback/memo.

Interview angle: compiler does not remove need to understand rendering—it optimizes proven patterns.

Teams enable gradually with lint rules and compatibility checks.

A strong answer is:

The React Compiler auto-memoizes where safe—I still understand render identity and dependencies because compilation can be incrementally adopted, and existing uncompiled code still uses the same React semantics.


Patterns, architecture, and coding scenarios

How do you avoid prop drilling?

What interviewers are testing: Whether you try composition and colocation before reaching for Context or a global store.

Options:

Approach When
Composition Pass children or render props
Context Wide low-churn values
Colocation Split components so intermediates disappear
Client store Many distant consumers

Do not reach for global state before trying composition and colocation.

A strong answer is:

I colocate state and compose children first; Context or a small store only when many distant components need the same client data.

What are React portals?

What interviewers are testing: Whether you know portals escape DOM layout constraints while remaining in the same React tree.

Portals render children into a different DOM node—typically document.body for modals and tooltips. They are common for modals and overlays because they can escape DOM layout/stacking constraints while remaining in the same React tree; accessibility still requires correct dialog semantics and focus management.

jsx
createPortal(<Modal />, document.getElementById("modal-root"));

Event bubbling still follows React tree (not DOM tree)—important for delegation tests.

A strong answer is:

Portals render UI elsewhere in the DOM while keeping React event bubbling logical—they escape layout and stacking constraints, but accessibility still requires correct dialog semantics and focus management.

Why must React state updates be immutable?

What interviewers are testing: Whether you treat state as an immutable snapshot and understand why mutation breaks reconciliation and memoization.

React state should be treated as an immutable snapshot. Mutating an existing object and passing the same reference back can prevent an expected update and also breaks assumptions used by memoization and concurrent rendering.

javascript
// Wrong — mutates
state.push(item);

// Right — new reference
setState([...state, item]);
setState({ ...state, count: state.count + 1 });
Output

A strong answer is:

I treat state as an immutable snapshot and create new objects or arrays for updates. Mutating old state can break update detection, memoization, and assumptions used by concurrent rendering.

How do synthetic events work in React?

What interviewers are testing: Whether you understand React's event abstraction, root-level delegation, and how modern SyntheticEvents differ from the old pooled-event model.

React wraps browser events in SyntheticEvent for cross-browser normalization.

Detail Interview note
Delegation React 17+ attaches to root container
preventDefault Still explicit for forms/links
No pooling (modern) React DOM no longer pools event objects; event.persist() is unnecessary on the web

Prefer controlled patterns over reading DOM after async without storing values.

A strong answer is:

SyntheticEvent gives React a consistent event interface while preserving browser event access through nativeEvent. In modern React DOM, event objects are no longer pooled; I mainly care about propagation, default prevention, and React's delegated event model.


React coding interview scenarios

Coding scenario: Build a todo list — what do interviewers evaluate?

What interviewers are testing: Whether you can structure state, keys, immutability, and accessibility for a small list feature under time pressure.

Expected features: add, toggle complete, filter (all/active/done), delete.

Criteria Strong signal
State shape Array of { id, text, done } not parallel arrays
Keys Stable id, not index
Immutability Map/filter for updates
Accessibility Labels, button types, list semantics
Edge cases Empty state, duplicate submit
jsx
function todosReducer(state, action) {
  switch (action.type) {
    case "add":
      return [...state, { id: crypto.randomUUID(), text: action.text, done: false }];
    case "toggle":
      return state.map((t) => (t.id === action.id ? { ...t, done: !t.done } : t));
    default:
      return state;
  }
}

Mention useReducer when transitions multiply—shows structure for growing state machines.

A strong answer is:

I model todos as an immutable array with stable ids, use reducer or useState clearly, filter without mutating, and wire accessible controls—not a quick DOM hack.

Coding scenario: Fix a component that loops infinitely — common causes?

What interviewers are testing: Whether you can diagnose self-triggering effects from dependency arrays and unstable identities.

Cause Symptom
Effect with no dependency array updates state Repeats after every render
Object/function dependency recreated each render Effect repeatedly re-runs
Effect updates state included in its own dependencies Self-triggering loop

Fix patterns:

  • Narrow dependencies to primitives
  • Functional updates: setItems((prev) => ...)
  • Move object creation outside effect or memoize
  • Do not derive state from state in effect when render can compute it

A strong answer is:

Infinite loops usually mean an effect writes state that retriggers itself—I fix dependency arrays, derive values in render instead of effects, and use functional updates.

Scenario: Users report a slow React dashboard — how do you investigate?

What interviewers are testing: Whether you start from user-visible impact and classify the bottleneck before jumping to React Profiler—rendering is only one possible cause.

Step Action
1 Reproduce and classify: startup/LCP, interaction/INP, navigation, network, or render
2 Check field/production telemetry if available
3 Inspect network waterfall and API timings
4 Use React Profiler when rendering is implicated
5 Check large lists, wide Context updates, expensive computations
6 Check bundle size and code splitting
7 Fix highest-impact bottleneck and re-measure

Connect to front end performance topics (LCP, INP).

A strong answer is:

I reproduce the symptom, check real-user metrics and network first, then profile renders if UI work is implicated—I fix the biggest measurable bottleneck before micro-optimizing hooks.


Final React interview checklist

  • Explain Virtual DOM, keys, and one-way data flow
  • useEffect deps, cleanup, Strict Mode extra mount cycle in dev
  • useMemo/useCallback only with justification
  • Server vs Client Components and when you would use each
  • TanStack Query vs raw fetch
  • Timed todo and debounced search coding reps
  • Error boundaries and testing with RTL
  • One performance and one production bug STAR story
  • Front end developer interview questions for broader UI fundamentals
  • Full stack developer interview questions if the role is end-to-end

Pattern cheat sheet (quick reference)

Need React starting point
Local UI state useState / useReducer
Side effects / subscriptions useEffect + cleanup
Server data TanStack Query / RSC
Avoid list bugs Stable key={item.id}
Expensive child renders memo + stable props (after profile)
Slow typing on filter useTransition
Heavy route lazy + Suspense
Forms (React 19) Actions + useActionState
Global theme/auth Context (low churn)
Modal overlay Portal + focus trap
Tests Testing Library + MSW

References

Official React documentation


Summary

React interviews in 2026 still start with fundamentals—components, JSX, props versus state, controlled inputs, and the Rules of Hooks—but panels quickly move to whether you can reason about rendering and data under real constraints. Expect hooks depth (useState snapshots, useEffect cleanup, custom hooks like useDebounce), state layering (local, Context, TanStack Query, Redux when justified), and performance judgment (memo, keys, transitions without breaking controlled inputs).

Mid-level loops add routing, error boundaries, Testing Library habits, React 19 Actions, and the modern bridge topics: Server Components, use(), Suspense, concurrent updates, React Compiler 1.0, and React 19.2 features such as useEffectEvent and <Activity />. Coding rounds reward immutable state, stable keys, debounced search with abort and loading guards, and calm debugging of self-triggering effects.

Use the prep sections and final checklist to rehearse aloud. When the role expects Fiber-level architecture, hydration, and production performance scenarios, continue with the experienced React article linked above.

Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)