Interview Questions on React JS for Experienced Developers

Interview questions on React JS in 2026 span basic JSX and state through experienced architecture—Fiber scheduling, Server Components, and production debugging. Interview questions on React JS for experienced candidates add scenario-based rounds: fix an infinite useEffect loop, design a dashboard data layer, or defend why you picked TanStack Query over Context. Basic interview questions on React JS still matter because senior loops often start with fundamentals before whiteboard depth.

Below are 45 React JS interview questions organized from a brief fundamentals refresher through experienced architecture and scenario-based answers. This article owns senior depth — Fiber/concurrency, React 19.2 APIs, React Compiler, RSC architecture, hydration, performance profiling, and production scenarios. For beginner/mid fundamentals (JSX, props/state, hooks, forms, routing, testing), see React interview questions and answers.

NOTE
Prep target: Master basics (props, state, keys) even for senior roles—then rehearse scenarios aloud: debounced search, stale closure fix, slow dashboard triage, and React 19.2 Actions, useOptimistic, useEffectEvent, and when framework/Query data layers beat hand-rolled fetch state. For each technical card, read What interviewers are testing aloud, then practice the full answer. Use A strong answer is as your ~20-second closing line.

Interview context and how to prepare

What React JS interviews actually test

React loops test whether you can ship correct UI as state changes—not whether you memorized 2018 lifecycle diagrams.

Layer What interviewers probe
Basics Components, JSX, props, state, lists
Hooks useState, useEffect, deps, custom hooks
Rendering Reconciliation, keys, when re-renders happen
Data Fetch patterns, TanStack Query, error handling
Experienced RSC, concurrency, perf profiling
Scenarios Debug loops, architecture trade-offs, live coding
Level Emphasis
Basic Controlled forms, keys, one-way data flow
Experienced (3–6 yr) State architecture, testing, API integration
Senior (6+ yr) System design, RSC, team standards, incidents

Basic vs experienced React JS interview questions

Basic questions Experienced / scenario questions
What is JSX? Why did this useEffect loop infinitely?
Props vs state Design data flow for admin table + filters
What are hooks? When RSC vs client component for this page?
Controlled input Debounce search without jank—walk through code
Virtual DOM definition Profile dashboard—what do you measure first?

Experienced rounds assume you already know basics and push judgment under ambiguity.

How scenario-based React interviews are structured

Typical flow:

  1. Situation — "Search re-fetches every keystroke and UI janks"
  2. Your diagnosis — missing debounce, no abort, parent re-render
  3. Fix — debounce + AbortController or TanStack Query
  4. Follow-up — "What if user types faster than network?"

Common scenario rounds include an infinite useEffect loop, child re-renders when props look unchanged, hydration mismatch, and large lists without virtualization.

Realistic prep plan for React JS interviews

Week Focus Output
1 Basic — JSX, props, state, lists, forms Todo without tutorial
2 Hooks — effects, cleanup, custom hooks useDebounce from scratch
3 Data — loading/error, Query vs useEffect Paginated list
4 Experienced — perf, Context vs store, testing Profiler screenshot story
5 Scenarios — timed debug + coding 3 scenario narrations
6 React 19/19.2 — Actions, useOptimistic, useEffectEvent, compiler awareness Mock whiteboard

Basic interview questions on React JS

What is React JS?

What interviewers are testing: Whether you understand React's declarative state→UI model and what React provides versus what frameworks provide. React is a JavaScript library for building user interfaces with a component-based, declarative model—you describe UI as a function of state; React updates the DOM when state changes.

Idea Meaning
Components Reusable UI units (Button, UserCard)
Declarative Describe what UI should look like
One-way data flow Props down, events up
Ecosystem Next.js, Remix, React Native

React is not a full framework—you choose routing, global state, and styling.

A strong answer is:

React is a component library for declarative UIs with predictable data flow—I use it when rich client interactivity and ecosystem depth matter.

What is JSX?

What interviewers are testing: Whether you know JSX is syntax transformed into React element/runtime calls, not HTML executed by the browser. JSX embeds HTML-like syntax in 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.

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

Rules: one parent (or Fragment), className not class, expressions in {}, close all tags.

A strong answer is:

JSX is syntax sugar for readable component trees—it compiles to JavaScript and is not a separate language or browser feature.

What is a React component?

What interviewers are testing: Whether you design reusable, composable UI boundaries rather than giant page components. A component is a function (or class) that returns UI. Function components are standard in 2026; hooks supply state and effects.

jsx
function Counter() {
  const [count, setCount] = React.useState(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

Components compose—pages are trees of smaller components.

A strong answer is:

A component is a reusable UI function with optional state—composition lets me build pages from small pieces instead of monolithic templates.

What are props?

What interviewers are testing: Whether you understand parent-owned inputs, immutability, and one-way ownership. Props (properties) are read-only inputs from parent to child—one-way data flow.

jsx
function Avatar({ src, alt }) {
  return <img src={src} alt={alt} />;
}

Children can be passed as props.children. Props must not be mutated by the child.

A strong answer is:

Props flow down and are immutable in the child—I treat them as function arguments for UI rendering.

What is state in React?

What interviewers are testing: Whether you know what data actually belongs in state versus derived values or external/server state.

Props State
Owned by Parent Component owning the state
Updated by Parent passes new value State setter/reducer
Purpose Inputs/configuration UI data that changes over time

Lift state up when siblings need to share it.

A strong answer is:

State is mutable local data that drives UI—when it changes, React re-renders; I lift state to the lowest common ancestor when siblings must share it.

Controlled vs uncontrolled components?

What interviewers are testing: Whether you can choose between React-owned and DOM-owned form state based on behavior and integration needs.

Type Source of truth Example
Controlled React state value={text} onChange={...}
Uncontrolled DOM ref to read input value

Basic interviews favor controlled inputs—predictable, testable, easy validation.

A strong answer is:

Controlled components keep form state in React—I default to them for forms unless I need file inputs or third-party widgets that fight controlled mode.

What is the Virtual DOM?

What interviewers are testing: Whether you understand reconciliation and identity, not repeat "Virtual DOM makes React fast." React builds an in-memory element tree representing UI. On update, React reconciles the next UI tree with the previous one and commits the DOM mutations needed to make the rendered output match.

Fiber (React 16+) is React's reconciliation architecture—Fiber's architecture enables React to prioritize, pause, resume, or abandon render work used by concurrent features.

A strong answer is:

Virtual DOM is React's lightweight UI representation for efficient diffing—Fiber underneath enables priorities and concurrent features, not just a simple full-tree compare.

Why do lists need keys?

What interviewers are testing: Whether you understand that keys preserve component identity and state across list changes. Keys help React identify which items changed, were added, or removed—stable identity across renders.

jsx
{items.map((item) => <li key={item.id}>{item.name}</li>)}
Key choice Result
Stable unique id Correct reuse
Array index Bugs on reorder/delete

A strong answer is:

Keys must be stable unique ids—not array index when the list can reorder or delete, or React reuses wrong component state.

What is one-way data flow?

What interviewers are testing: Whether you can trace data and events through a component tree without hidden mutation. Data flows down via props; events flow up via callbacks. Parents own shared state; children request changes through handlers.

This predictability simplifies debugging—trace props from root.

A strong answer is:

One-way flow means parents own state and pass callbacks—no child silently mutating parent data, which keeps large trees debuggable.

How do you conditionally render in React?

What interviewers are testing: Whether you can structure branching UI without creating unreadable render logic. Patterns:

jsx
{isLoggedIn ? <Dashboard /> : <Login />}
{error && <ErrorBanner message={error} />}
{items.length === 0 ? <Empty /> : <List items={items} />}

Prefer explicit branches for complex cases over nested ternaries.

A strong answer is:

I use ternary or short-circuit for simple cases and early returns or small subcomponents when conditional UI grows—readability beats clever one-liners.

What are React Fragments?

What interviewers are testing: Whether you understand when an extra DOM wrapper would alter layout or semantics. Fragments group children without extra DOM nodes:

jsx
return (
  <>
    <Title />
    <Body />
  </>
);

Avoids wrapper <div> that breaks CSS layout or semantics.

A strong answer is:

Fragments let me return multiple siblings without a useless wrapper div that would break flex or grid layouts.


Hooks, rendering, and mid-level depth

What are the rules of hooks?

What interviewers are testing: Whether you know normal Hook rules and the documented exception for React's use API.

  1. Call hooks only at the top level—not inside loops, conditions, or nested functions (for normal Hooks such as useState and useEffect)
  2. Call hooks only from React function components or custom hooks

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

Exception: React's use API is different from normal Hooks: it may be called conditionally or in loops, but it still must be called from a component/Hook and cannot be wrapped in try/catch.

A strong answer is:

Normal Hooks such as useState and useEffect must run at the top level in a consistent order and only from React components or custom Hooks. The use API is a documented exception that can appear conditionally or in loops.

How does useState work?

What interviewers are testing: Whether you understand render snapshots, queued updates, and functional updaters. useState returns [value, setter]. Updates schedule a re-render. Setters accept a value or functional updater prev => next.

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

  function incrementTwiceWrong() {
    setCount(count + 1);
    setCount(count + 1);
  }

  function incrementTwiceCorrect() {
    setCount(c => c + 1);
    setCount(c => c + 1);
  }

  return <button onClick={incrementTwiceCorrect}>{count}</button>;
}

Direct updates both use the current render's count; functional updates are applied in sequence. That teaches render snapshots—the value you read during a render is fixed until the next render.

A strong answer is:

useState queues re-renders on update—I use functional setState when the next value depends on the previous, especially in async or batched callbacks.

What does useEffect do?

What interviewers are testing: Whether you use Effects to synchronize with external systems, rather than as a general "run code after render" tool. useEffect runs side effects after React commits an update—for fetch, subscriptions, and DOM sync.

jsx
useEffect(() => {
  document.title = `Count: ${count}`;
}, [count]);
Dependency array Behavior
Omitted Every render (rare, risky)
[] Effect setup has no reactive dependencies, so after the initial commit it normally does not rerun because of component state/prop changes; cleanup runs on unmount. Development Strict Mode can additionally perform a setup → cleanup → setup stress cycle
[a, b] When a or b change

Return a cleanup function for teardown.

A strong answer is:

useEffect is for synchronizing with external systems after render—I declare dependencies explicitly and return cleanup for subscriptions and abort controllers.

What is the stale closure problem in useEffect?

What interviewers are testing: Whether you can fix stale Effect closures with dependencies, functional updates, refs, or useEffectEvent. Effects close over values from the render when they were created. If dependencies are wrong, the effect sees old state/props.

Fix:

  • Correct dependencies when the value should trigger resynchronization
  • Functional updates when only previous state is needed
  • useEffectEvent when Effect logic should read the latest committed value without making it reactive
  • Refs for imperative/non-render state where appropriate

A strong answer is:

Stale closures happen when code captures an older render. I fix reactive dependencies properly, use functional state updates when the next value depends on previous state, and use useEffectEvent for non-reactive Effect logic that needs the latest committed values. Refs remain useful for imperative mutable state.

When do you use useMemo and useCallback?

What interviewers are testing: Whether you memoize for measured benefit or precise control—not by default everywhere.

Hook Memoizes Use when
useMemo Computed value Expensive derive; stable object for child memo
useCallback Function reference Stable callback for memoized child

React Compiler is a separate build-time tool, not something built into React 19 automatically. It works best with React 19 but also supports React 17 and 18.

Do not wrap everything—memo has cost.

A strong answer is:

I memoize manually when I need precise control or profiling justifies it. Where React Compiler is enabled, I generally let the compiler handle routine memoization rather than adding useMemo and useCallback everywhere.

What is useRef used for?

What interviewers are testing: Whether you distinguish mutable non-render state from UI-driving state. useRef holds a mutable box that persists across renders without causing re-render when .current changes.

Uses: DOM refs, timer ids, AbortController, latest value for callbacks.

A strong answer is:

useRef stores values that survive renders but shouldn't trigger them—DOM nodes, interval ids, or latest props for event handlers.

What are custom hooks?

What interviewers are testing: Whether you can extract reusable stateful behavior without accidentally sharing state. Functions starting with use that compose built-in hooks—reusable stateful logic.

jsx
function useDebounce(value, delayMs) {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const id = setTimeout(() => setDebounced(value), delayMs);
    return () => clearTimeout(id);
  }, [value, delayMs]);
  return debounced;
}

Custom hooks share logic, not state—each call gets isolated state.

A strong answer is:

Custom hooks extract reusable behavior—debounce, fetch, media query—without duplicating effect logic across components.

When do you prefer useReducer over useState?

What interviewers are testing: Whether state complexity is driven by explicit transitions/actions rather than number of fields alone. useReducer suits complex state transitions with multiple actions—forms with many fields, wizards, state machines.

javascript
function todosReducer(state, action) {
  switch (action.type) {
    case "add":
      return [...state, { id: action.id, text: action.text, done: false }];
    case "toggle":
      return state.map((t) =>
        t.id === action.id ? { ...t, done: !t.done } : t
      );
    default:
      return state;
  }
}

let state = [];
state = todosReducer(state, { type: "add", id: 1, text: "learn" });
state = todosReducer(state, { type: "toggle", id: 1 });
console.log(state[0].done);
Output

Running prints true—immutable updates in the reducer keep state predictable.

A strong answer is:

useReducer when next state depends on action type and prior state in non-trivial ways—todo apps, multi-step flows—not for a single boolean toggle.

What is lifting state up?

What interviewers are testing: Whether you place shared state at the lowest common ancestor without duplicating sources of truth. Move shared state to the closest common ancestor of components that need it; pass data and callbacks down.

Avoids duplicate sources of truth and sync bugs between siblings.

A strong answer is:

I lift state to the parent that owns the shared truth—two siblings editing the same filter share one state object and callbacks, not duplicated useState.

When should you use React Context?

What interviewers are testing: Whether you can avoid both prop-drilling dogma and global-context re-render problems. Context passes data through the tree without prop drilling—theme, locale, auth session.

Good for Poor for
Low-churn global UI settings High-frequency updates (causes wide re-renders)
Auth user object Large app state (prefer colocation + Query/store)

Split contexts by update frequency when needed.

A strong answer is:

Context for rarely changing cross-cutting data—I split contexts or use selectors/stores when updates are frequent to avoid re-rendering the whole tree.


Interview questions on React JS for experienced developers

What is React Fiber?

What interviewers are testing: Whether you understand Fiber as React's internal work/reconciliation architecture, not an API developers manipulate. Fiber is React's reconciliation engine—each unit of work is a fiber node representing a component instance.

Enables:

  • Incremental rendering — pause and resume
  • Priorities — urgent updates (input) before transitions
  • Concurrent features — useTransition, useDeferredValue

Fiber is the reconciler/work architecture for interruptible render work, prioritization, scheduling, and reconciliation units. Use useEffect documentation when discussing effect timing—not Fiber directly.

A strong answer is:

Fiber is the work unit for reconciliation—it enables concurrent rendering and priority scheduling for interruptible updates.

What is concurrent rendering?

What interviewers are testing: Whether you distinguish interruptible scheduling from parallel JavaScript execution. React can start, pause, and abandon renders to keep UI responsive. useTransition marks non-urgent updates; useDeferredValue lags behind fast-changing input.

jsx
const deferredQuery = useDeferredValue(query);

const filtered = useMemo(
  () => hugeFilter(deferredQuery),
  [deferredQuery]
);

startTransition marks a state update as non-urgent, but synchronous work inside the callback—such as hugeFilter(query)—can still block the main thread. For expensive filtering, defer the input value and memoize, or move heavy computation to a Web Worker or a better data strategy.

Not the same as async/await—it's scheduling, not parallelism.

A strong answer is:

Concurrent rendering keeps typing responsive while heavy filters catch up—I use transitions for non-urgent UI updates, not as a replacement for proper data fetching architecture.

What are React Server Components (RSC)?

What interviewers are testing: Whether you can decide what belongs on the server versus the client boundary. Server Components render ahead of time in a server/build environment and their component code is not sent to the browser. They can access server-side data sources directly when the framework/runtime environment permits it.

Server Component Client Component ("use client")
No useState/useEffect Hooks, browser APIs, interactivity
Zero client bundle for logic Ships JS to browser
Serialize props to client tree Receives serialized props

Frameworks like Next.js App Router compose both in one tree.

A strong answer is:

RSC moves data-heavy, non-interactive UI to the server—client components handle interactivity; I don't put useEffect fetch on server components.

What are React 19 Actions and useActionState?

What interviewers are testing: Whether you understand React's mutation/action lifecycle, not just a replacement syntax for fetch. Actions are functions executed in React's transition/action lifecycle and may perform side effects. React DOM integrates Actions particularly well with forms. useActionState tracks the resulting state and pending status.

jsx
const [state, formAction, isPending] = useActionState(saveUser, null);
// <form action={formAction}>...</form>

useFormStatus lets child buttons read parent form pending state without prop drilling.

Known/validation errors may be returned as state; thrown errors can be handled by an Error Boundary.

A strong answer is:

Actions integrate mutations with React's transition lifecycle. I use useActionState when I need mutation result and pending state, especially for forms; expected validation errors can be returned as state and unexpected failures can surface through an Error Boundary.

What is useOptimistic?

What interviewers are testing: Whether you understand optimistic UI as temporary presentation while authoritative state settles. useOptimistic temporarily presents the anticipated state while an Action is pending. After the underlying state/action settles, the UI resolves back to the authoritative state. Error presentation and retry UX are still your responsibility.

A strong answer is:

useOptimistic gives first-class optimistic UI while an Action is pending—the authoritative state still wins, so I still handle failure and retry explicitly.

TanStack Query vs useEffect for data fetching?

What interviewers are testing: Whether you distinguish server-state lifecycle/caching from generic Effects and client state.

useEffect + fetch TanStack Query
Caching Manual Built-in
Deduping Manual Automatic
Stale/refetch Manual staleTime, window focus
Loading/error Manual flags Standardized

For reusable server-state fetching, caching, invalidation, retries, and deduplication, use a framework data layer or client cache such as TanStack Query. Direct Effect-based fetching remains valid for client-only cases, but you must handle races, cancellation, caching, and lifecycle yourself. Framework loaders/RSC may remove the need for either in many routes.

A strong answer is:

I avoid treating server data as ordinary component Effects when a framework loader, RSC data layer, or Query cache already owns that lifecycle. For client-side server state, TanStack Query gives caching, invalidation, dedupe, and retry semantics I would otherwise rebuild.

What are error boundaries?

What interviewers are testing: Whether you know which failures they isolate and which they do not. Class components (or library wrappers) implementing getDerivedStateFromError / componentDidCatch catch render errors in children—show fallback UI instead of white screen.

Traditional Error Boundaries catch errors thrown while rendering descendant React trees and in lifecycle methods. They do not automatically catch arbitrary errors thrown from event handlers or unrelated asynchronous callbacks. Server/framework error handling has its own boundary semantics.

A strong answer is:

Error boundaries isolate render failures per route or widget—I pair them with route-level fallbacks and logging, not try/catch around every onClick.

How do you test React components?

What interviewers are testing: Whether tests verify observable behavior/accessibility rather than implementation details. React Testing Library — test behavior users see, not implementation details.

Practice Why
Query by role/label Accessibility-aligned
userEvent over fireEvent Realistic interaction
Mock network at HTTP layer Stable integration tests
Avoid testing internal state Refactor-friendly

A strong answer is:

I test what users see—roles, labels, outcomes—not component state or hook call counts, so refactors don't break tests unnecessarily.

How do you reduce React bundle size?

What interviewers are testing: Whether you measure and split expensive delivery boundaries before micro-optimizing rendering.

Technique Use
Route/framework splitting Load route code only where needed
React.lazy + Suspense Lazily load a client component
Dynamic import Heavy optional widgets
RSC/server rendering Keep server-only component logic out of client bundle

Measure with webpack/vite analyzer before micro-optimizing hooks.

A strong answer is:

I split by route and heavy widgets first—lazy charts and admin pages—then analyze bundle; memoization is not a substitute for code splitting.

Why does Strict Mode double-invoke effects in development?

What interviewers are testing: Whether you understand why development Strict Mode stress-tests Effects and rendering. In development, Strict Mode intentionally performs extra render checks and runs an additional Effect setup → cleanup → setup cycle to expose impure rendering and missing cleanup.

In production, Effects run according to their dependencies—after initial commit, again when dependencies change, with cleanup before the next setup and on unmount. Development Strict Mode additionally performs an extra setup/cleanup/setup cycle on initial mount to expose missing cleanup and non-idempotent logic.

A strong answer is:

Strict Mode double effects in dev expose missing cleanup—I write idempotent effects with teardown, not hacks to disable Strict Mode.

What is hydration and what causes hydration mismatches?

What interviewers are testing: Whether you understand that initial server/client output must be deterministic. Hydration attaches client React to server-rendered HTML. Mismatch when server HTML ≠ client first render—causes warnings and broken UI.

Common causes: Date.now(), Math.random(), browser-only APIs in SSR, invalid HTML nesting.

A strong answer is:

Hydration requires server and client first paint to match—I gate browser-only values behind useEffect or suppress only when truly unavoidable with clear comments.


Scenario-based interview questions on React JS for experienced

Scenario: A page freezes — useEffect runs in an infinite loop. How do you debug?

What interviewers are testing: Whether you can identify an Effect that updates state which changes one of its own dependencies, or a dependency whose identity changes every render.

Symptoms: Browser tab hangs; Network tab shows repeated identical requests.

Common cause Fix
setState in effect without deps guard Add deps or derive in render
[obj] dep — new object each render Depend on primitives or useMemo
Effect sets state that retriggers effect Remove redundant state

Walkthrough: Open component → find useEffect → check dependency array → check if setState inside always runs → move derivation to render or narrow deps.

A strong answer is:

I find the effect writing state that retriggers itself—fix deps, use functional updates, or compute during render instead of syncing state in an effect.

Scenario: Search box hammers the API on every keystroke. Fix it.

What interviewers are testing: Whether you can stop request storms with debounce, cancellation, and appropriate client/server data tooling.

Diagnosis: No debounce; possibly no request cancellation.

Fix stack:

  1. Debounce input—for example 250–400 ms depending on UX/query cost (useDebounce custom hook)
  2. AbortController in effect cleanup
  3. useTransition if filtering large local lists (keeps expensive React updates non-urgent—it does not debounce API calls)
  4. TanStack Query with enabled: debouncedQuery.length > 0
javascript
function debounce(fn, ms) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), ms);
  };
}
let calls = 0;
const search = debounce(() => { calls += 1; }, 100);
search(); search(); search();
setTimeout(() => console.log(calls), 150);
Output

After ~150 ms, calls is 1—only the trailing keystroke fired.

A strong answer is:

Debounce the query, abort stale fetches, show loading state—or use Query with debounced key; I'd never fire raw onChange directly to the API.

Scenario: Memoized child still re-renders when parent updates. Why?

What interviewers are testing: Whether you can diagnose memo failures from changing context values or unstable prop references. Checklist:

Check Issue
Context value changes Consumers of that context can re-render
Provider recreates {...} value each render Context value identity changes
Props objects/functions recreated memo sees changed references
Child itself owns changing state memo cannot block its own state update
Child not actually memoized Missing memo

Fix: useCallback/useMemo only after profiling, move state down, split context, or pass primitive props.

A strong answer is:

Unstable callback or object props break memo—I stabilize with useCallback when profiling proves it, or colocate state so the child isn't under a hot parent.

Scenario: Dashboard with charts and tables is slow. Your investigation plan?

What interviewers are testing: Whether you profile network, render, and interaction bottlenecks before sprinkling memoization.

Step Action
1 React Profiler — which components render often?
2 Network — waterfall, overfetch, missing pagination?
3 Lists — is a large rendered list dominating DOM/layout/render cost? Profile whether virtualization would help
4 Charts — dynamic import heavy libs?
5 State — context at root updating frequently?
6 Metrics — INP, LCP from field data

Prioritize user-visible wins before hook micro-optimization.

A strong answer is:

Profiler plus network first—I fix overfetch and unvirtualized lists before sprinkling useMemo; verify with Core Web Vitals, not gut feel.

Scenario: Design auth state for a React SPA with protected routes.

What interviewers are testing: Whether you design auth bootstrap, protected routes, and session handling without flash or token exposure. Approach:

  • Auth context or lightweight store with { user, status: 'loading' | 'authenticated' | 'anonymous' }
  • Bootstrap — single /me fetch on app load; avoid flash of wrong route
  • Protected route — render skeleton while loading; redirect only when status known
  • Token storage — for browser-based sessions, HttpOnly, Secure, appropriately configured SameSite cookies reduce token exposure to JavaScript, but cookie-based authentication also requires an explicit CSRF strategy where applicable
  • Refresh — handle session expiry/refresh according to the backend authentication model

Mention coordination with full stack API auth patterns.

A strong answer is:

Loading gate before redirect, single source of auth truth, httpOnly cookies when backend allows—I never redirect unauthenticated users before bootstrap finishes.

Scenario: Multi-step form with validation — how do you structure state?

What interviewers are testing: Whether you structure multi-step form state with one source of truth and step validation. Options:

Approach When
Single object + useReducer Medium wizard, clear actions
React Hook Form + Zod Many fields, schema validation
URL step param Shareable step, back button

Keep one source of truth; validate per step; persist draft to sessionStorage if UX requires.

A strong answer is:

useReducer or RHF with schema validation—one state machine for steps, persist optional draft, disable Next until step valid.

Scenario: Migrate class components to hooks in a legacy codebase. Strategy?

What interviewers are testing: Whether you migrate classes to hooks by responsibility—not by mechanical lifecycle-to-Effect mapping.

Phase Action
1 Lint rules block new class components
2 Leaf components first—low risk
3 For each lifecycle method, identify its responsibility: derive values during render, move user-triggered work into event handlers, and use Effects only for external synchronization with cleanup
4 Extract custom hooks from repeated logic
5 Tests before refactor—RTL behavior tests

Do not big-bang rewrite—strangle by route or feature flag.

A strong answer is:

I migrate leaf components behind behavior tests, but I don't mechanically translate lifecycle methods into Effects. I separate render derivation, user events, and true external synchronization, then extract reusable behavior into custom Hooks.

Scenario: Take-home React app — what do senior reviewers evaluate?

What interviewers are testing: Whether you know what senior reviewers evaluate in a take-home beyond feature completeness.

Area Signal
README Trade-offs, what you'd do with more time
State Clear boundaries, no prop drilling mess
Data Loading/error/empty states
Tests Critical paths covered
A11y Labels, focus, keyboard
Structure Feature folders, not 2000-line App

Over-engineering Redux for three fields scores poorly.

A strong answer is:

I ship clear README trade-offs, loading/error paths, a few meaningful tests, and accessible forms—polish on architecture judgment, not animation libraries on day one.

Scenario: How would you structure Suspense boundaries on a dashboard?

What interviewers are testing: Whether you place Suspense boundaries only around integrations that actually suspend.

Region Boundary strategy
Page shell Keep chrome outside Suspense so navigation stays stable
Charts / tables Separate Suspense per expensive widget with tailored fallbacks
Shared filters Avoid one giant boundary that blanks the whole page
Errors Pair boundaries with error boundaries per region

A Suspense boundary only helps for code/data sources integrated with Suspense; wrapping arbitrary useEffect fetching in <Suspense> does not make it suspend.

A strong answer is:

I use granular Suspense boundaries so one slow chart does not blank the entire dashboard, and I keep filters/chrome outside the suspended regions.

Scenario: How do you separate reactive vs non-reactive effect logic?

What interviewers are testing: Whether you can separate reactive Effect dependencies from non-reactive logic using useEffectEvent. useEffectEvent lets Effect logic read the latest committed props/state without making those values reactive dependencies.

jsx
const onConnected = useEffectEvent(() => {
  showNotification('Connected', theme);
});

useEffect(() => {
  const connection = createConnection(roomId);
  connection.on('connected', onConnected);
  connection.connect();

  return () => connection.disconnect();
}, [roomId]);
Teaching point Detail
roomId is reactive Keep it in the dependency array
theme read via Effect Event Latest value without reconnecting
Effect Event identity Not stable—do not put onConnected in dependencies
Do not misuse Not a loophole to hide dependencies; not general event handlers

A strong answer is:

I keep values that should resynchronize the Effect in its dependency list. For non-reactive Effect logic that needs the latest committed values, React 19.2's useEffectEvent lets me read them without restarting the subscription.

Scenario: How do you diagnose a 2-second INP interaction?

What interviewers are testing: Whether you can profile interaction delay and distinguish rendering, JS, and layout bottlenecks.

Step Action
1 Reproduce the interaction in Performance/Profiler
2 Check long tasks on the main thread during input
3 Inspect expensive renders, large lists, sync JSON parsing
4 Look for blocking work in event handlers before paint
5 Validate field INP/LCP with real-user metrics

A strong answer is:

I profile the exact interaction, identify the long task—rendering, JavaScript, layout, parsing, or event-handler work—and remove or chunk the bottleneck. I use transitions only when the delay comes from non-urgent React rendering; CPU-heavy work may need chunking or a Web Worker.

Scenario: How would you migrate a large SPA toward RSC/framework rendering?

What interviewers are testing: Whether you migrate toward RSC through framework-supported incremental slices.

Phase Action
0 Choose a framework/runtime that supports RSC and establish the server/client boundary
1 Identify server-safe, non-interactive surfaces first
2 Move data fetching for those surfaces to Server Components or loaders
3 Keep client components for hooks, browser APIs, and interactivity
4 Migrate route by route behind feature flags
5 Measure bundle size and hydration cost after each slice

A strong answer is:

I first choose a framework architecture that supports Server Components. Then I migrate read-heavy, server-safe surfaces incrementally, keep interactive islands client-side, and measure client-JS/hydration improvements rather than attempting a whole-SPA rewrite.

Scenario: How do React Compiler and manual memoization interact?

What interviewers are testing: Whether you know when React Compiler handles memoization and when manual memo remains appropriate.

Situation Guidance
New code compiled by React Compiler Let compiler handle routine memoization
Existing manual memoization Don't remove mechanically; test because output/behavior may change
Precise semantic/stability requirement useMemo / useCallback remain valid escape hatches
Uncompiled/library boundary Manual memoization may still matter
Performance problem Profile before adding optimization

A strong answer is:

I rely on the React Compiler where enabled, but I still understand manual memo for uncompiled code, unstable library boundaries, and profiler-proven hot paths.


Final prep checklist

Use the final week to rehearse basics and scenarios—not to memorize every API name.

  • Basic — props, state, keys, controlled inputs
  • Hooks — effect deps, cleanup, stale closure fix, useEffectEvent
  • Experienced — RSC vs client, Query vs useEffect
  • React 19.2 — Actions, useOptimistic, compiler awareness
  • Scenarios — infinite loop, debounced search, slow dashboard
  • Timed todo and search coding reps
  • React interview questions and answers companion drills
  • Front end fundamentals
  • Full stack integration if end-to-end role

Pattern cheat sheet (quick reference)

Need React approach
Basic list Stable key={item.id}
Form input Controlled value + onChange
Side effect useEffect + deps + cleanup
Expensive child Profile first; then memo / stable props
Client-managed server state Framework data API or TanStack Query
Reduce API requests while typing Debounce + stale-request cancellation
Keep expensive React update non-urgent startTransition / useDeferredValue
Global theme/locale Context (split if needed)
Render error fallback Error boundary
Less client JS RSC + route code splitting
Form mutation (React 19) Actions + useActionState

References


Summary

Experienced React interviews combine fundamentals with production judgment: infinite-loop debugging, debounced search, dashboard performance, and architecture choices you can defend aloud. Pair with React interview questions and answers for more coding drills and front end interviews for browser-wide context.

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)