Skip to content

React Interview Questions and Answers for 2026

May 21, 202525 min read

React interviews have changed. Knowing what useState returns is still useful, but it won’t carry a mid-level or senior interview. Interviewers increasingly test whether you understand state identity, Effect synchronization, async user interfaces, server boundaries, performance evidence, accessibility, and the APIs introduced in React 19.

These React interview questions and answers for 2026 are based on React’s current official documentation, which covers React 19.2. That release includes <Activity>, useEffectEvent, React Performance Tracks, and other additions, while React Compiler 1.0 is now stable. See the current React versions and the React 19.2 release notes.

The strongest interview answer usually has three layers: a direct explanation, the trade-off that affects a real application, and a small example that proves you understand the behavior.

Table of Contents

  1. How to Use These React Interview Questions

  2. React Fundamentals Interviewers Still Test

  3. State, Events, and Effects

  4. React 19.2 Interview Questions

  5. Server Rendering and React Server Components

  6. Performance, Accessibility, and Testing

  7. Upgrading from React 18 to React 19

  8. Frequently asked questions (FAQ)

  9. What to Practise Before the Interview

How to Use These React Interview Questions

The level beside each question indicates the depth normally expected. A junior candidate should explain the rule and produce working code. A mid-level candidate should also discuss failure modes. A senior candidate should connect the behavior to architecture, performance, deployment, or maintenance.

Don’t memorise every paragraph. Practise giving the short answer first, then expand only when the interviewer asks for more detail. That approach keeps a correct answer from becoming an unfocused lecture.

React Fundamentals Interviewers Still Test

1. What is JSX, and what does React do with it?

Level: Junior

Short interview answer: JSX is a JavaScript syntax extension for describing user-interface markup. A build tool transforms JSX into calls understood by the React JSX runtime, producing React elements that describe the intended UI. JSX does not create DOM nodes directly.

Deeper technical explanation: Older explanations often say JSX always becomes React.createElement() calls. That describes the classic transform, but modern React projects normally use the newer JSX transform and functions from the JSX runtime. React 19 requires this modern transform. During rendering, React evaluates the resulting element tree; during the commit phase, React applies necessary changes to the host environment, such as the browser DOM.

Runnable example:

export default function Price({ amount }) {
  const formatted = new Intl.NumberFormat("en-IN", {
    style: "currency",
    currency: "INR",
  }).format(amount);

  return <output aria-label="Total price">{formatted}</output>;
}

Common wrong answer: “JSX is HTML inside JavaScript, and the browser reads it directly.” Browsers don’t natively execute JSX, and JSX differs from HTML in areas such as expressions, property names, and closing-tag rules.

Likely follow-up question: Why must a React component remain pure during rendering?

Official React source: Writing Markup with JSX and the React 19 upgrade guide.

2. Why are stable keys important in React lists?

Level: Junior to mid-level

Short interview answer: A key gives a child identity among its siblings. React uses that identity to match children between renders, preserve the correct component state, and determine whether an item moved, appeared, or disappeared.

Deeper technical explanation: An array index is acceptable only when the list is effectively static: items aren’t reordered, inserted, or deleted. In a mutable list, an index identifies a position rather than a record. That can attach input values or component state to the wrong item after a reorder. Random keys are worse because every render gives each child a new identity, forcing state and DOM to be recreated.

Runnable example:

import { useState } from "react";

const initial = [
  { id: "a1", name: "Asha" },
  { id: "b2", name: "Bilal" },
];

export default function Team() {
  const [people, setPeople] = useState(initial);

  return (
    <>
      <button onClick={() => setPeople(p => [...p].reverse())}>
        Reverse order
      </button>
      {people.map(person => (
        <label key={person.id}>
          <input type="checkbox" /> {person.name}
        </label>
      ))}
    </>
  );
}

Common wrong answer: “Keys only remove a console warning and make rendering faster.” Their more important purpose is identity and correct state preservation.

Likely follow-up question: Can a key be used outside a list? Yes. Changing a component’s key can deliberately reset its state.

3. What is the difference between controlled and uncontrolled inputs?

Level: Junior

Short interview answer: A controlled input receives its current value from React state and updates that state through an event handler. An uncontrolled input keeps its current value in the DOM and is usually read through FormData or a ref.

Deeper technical explanation: Controlled inputs are useful when another part of the interface needs the current value immediately, such as live validation or a filtered preview. Uncontrolled inputs can reduce state plumbing when values are needed only on submission. A text input must not switch between controlled and uncontrolled during its lifetime, and every controlled input needs a synchronous onChange update.

Runnable example:

import { useState } from "react";

export default function SearchForm() {
  const [query, setQuery] = useState("");

  function submit(event) {
    event.preventDefault();
    const data = new FormData(event.currentTarget);
    alert(`${query}: ${data.get("note")}`);
  }

  return (
    <form onSubmit={submit}>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <input name="note" defaultValue="Optional note" />
      <button>Search</button>
    </form>
  );
}

Common wrong answer: “Controlled is always better.” The right choice depends on who needs to own and react to the value.

Likely follow-up question: Why can’t a file input be controlled like a text input?

Official React source: React input reference.

State, Events, and Effects

4. How do React events and batched state updates behave?

Level: Junior to mid-level

Short interview answer: React passes event handlers a normalized event object and batches state updates made during an interaction. State is a snapshot for the current render, so functional updater syntax is necessary when the next value depends on the queued previous value.

Deeper technical explanation: React’s event abstraction provides familiar methods such as preventDefault() and stopPropagation(). Synthetic events have not been pooled since React 17, so e.persist() is no longer necessary. This corrects a common outdated interview answer. Event propagation and default browser behavior are separate concepts.

Two calls to setCount(count + 1) both use the same captured count. Two functional updates process sequentially.

Runnable example:

import { useState } from "react";

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

  async function incrementTwice(event) {
    setCount(value => value + 1);
    setCount(value => value + 1);
    await Promise.resolve();
    console.log(event.type); // "click"
  }

  return <button onClick={incrementTwice}>Count: {count}</button>;
}

Common wrong answer: “Every state setter immediately changes the variable.” It queues work for a later render; it doesn’t mutate the state snapshot already used by the handler.

Likely follow-up question: What is the difference between stopPropagation() and preventDefault()?

5. When should you use useReducer instead of useState?

Level: Mid-level

Short interview answer: Use useState for independent, straightforward values. Consider useReducer when several state fields change together, transitions have meaningful names, or update logic has become difficult to understand across multiple handlers.

Deeper technical explanation: A reducer centralises transition logic in a pure function. That can make complex workflows easier to test and review, but it doesn’t automatically make state global. Context, Redux Toolkit, Zustand, and reducers solve different problems. For a broader state-ownership decision, see this comparison of React Context and Redux.

Runnable example:

import { useReducer } from "react";

function reducer(state, action) {
  if (action.type === "increment") return { count: state.count + 1 };
  if (action.type === "reset") return { count: 0 };
  throw new Error("Unknown action");
}

export default function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <>
      <button onClick={() => dispatch({ type: "increment" })}>
        {state.count}
      </button>
      <button onClick={() => dispatch({ type: "reset" })}>Reset</button>
    </>
  );
}

Common wrong answer: “Use useReducer whenever an object has more than one property.” Complexity of transitions matters more than object size.

Likely follow-up question: Why must a reducer be pure?

Official React source: useReducer reference.

6. What is the correct mental model for useEffect?

Level: Mid-level

Short interview answer: An Effect synchronizes a React component with an external system. Its setup starts synchronization, its cleanup stops it, and React repeats that cycle when a reactive dependency changes.

Deeper technical explanation: Effects are suitable for subscriptions, browser APIs, network connections, and non-React widgets. They usually aren’t needed for deriving display data from props or handling a known user action. Dependencies aren’t a manual scheduling preference; they describe the reactive values the Effect reads. Suppressing the dependency linter commonly creates stale closures.

Strict Mode runs an additional development-only setup and cleanup cycle to expose incomplete cleanup. For related implementation details, see this guide to React useEffect cleanup.

Runnable example:

import { useEffect, useState } from "react";

export default function NetworkStatus() {
  const [online, setOnline] = useState(navigator.onLine);

  useEffect(() => {
    const update = () => setOnline(navigator.onLine);
    window.addEventListener("online", update);
    window.addEventListener("offline", update);

    return () => {
      window.removeEventListener("online", update);
      window.removeEventListener("offline", update);
    };
  }, []);

  return <p>{online ? "Online" : "Offline"}</p>;
}

Common wrong answer: “An empty dependency array guarantees the Effect runs exactly once.” Development checks, remounts, and visibility boundaries can produce additional setup cycles.

Likely follow-up question: What usually causes a useEffect infinite loop?

7. What problem does useEffectEvent solve?

Level: Mid-level to senior

Short interview answer: useEffectEvent lets Effect logic read the latest committed props and state without making that non-reactive logic cause the surrounding Effect to resynchronize.

Deeper technical explanation: Consider a connection that should restart when roomId changes, but whose “connected” notification should use the latest theme. Making theme an Effect dependency reconnects unnecessarily. An Effect Event can read the current theme while the connection Effect remains reactive only to roomId.

This API is not a way to hide legitimate dependencies. Effect Events may be called only from Effects or other Effect Events, and they shouldn’t be passed to children.

Runnable example:

import { useEffect, useEffectEvent } from "react";

export default function Clock({ onTick }) {
  const tick = useEffectEvent(() => onTick(new Date()));

  useEffect(() => {
    const id = setInterval(() => tick(), 1000);
    return () => clearInterval(id);
  }, []);

  return <p>The parent receives the latest tick handler.</p>;
}

Common wrong answer:useEffectEvent is a replacement for useCallback.” It separates reactive synchronization from event-like Effect logic; it is not a general memoization tool.

Likely follow-up question: Why should an Effect Event not appear in the dependency array?

Official React source: useEffectEvent reference.

React 19.2 Interview Questions

8. What are Actions, useActionState, and useOptimistic in React 19?

Level: Mid-level to senior

Short interview answer: An Action is a function used in a Transition to perform an async mutation while React coordinates pending states, errors, and UI updates. Form Actions integrate this model with <form action={fn}>; useActionState stores an Action’s result, while useOptimistic displays a temporary expected result during the operation.

Deeper technical explanation: Actions reduce repetitive code around form submission, pending indicators, and async state transitions. They don’t remove the need for server-side validation, authorization, idempotency, or error handling. A Server Function may be used as a form Action in a supporting framework, but not every Action is a Server Function.

Runnable example:

import { useActionState, useOptimistic } from "react";

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

export default function NameForm() {
  const [optimisticName, showOptimistic] = useOptimistic("");
  const [message, submit, pending] = useActionState(
    async (_, formData) => {
      const name = String(formData.get("name")).trim();
      showOptimistic(name);
      await wait(600);
      return name ? `Saved ${name}` : "Name is required";
    },
    ""
  );

  return (
    <form action={submit}>
      <input name="name" />
      <button disabled={pending}>Save</button>
      <p>{pending ? `Saving ${optimisticName}…` : message}</p>
    </form>
  );
}

Common wrong answer: “Optimistic UI means permanently updating state before checking the response.” Optimistic state is temporary and must converge with confirmed application state or roll back after failure.

Likely follow-up question: How would you prevent two rapid submissions from creating duplicate records?

Official React source: React 19 Actions, useActionState, and useOptimistic.

9. How does React’s use API differ from a Hook?

Level: Mid-level to senior

Short interview answer: use reads a resource such as a Promise or context. When it reads a pending Promise, the component suspends until that Promise settles. Despite its name, use is not a conventional Hook and may be called inside conditions and loops, although it must still run inside a component or Hook.

Deeper technical explanation: A Promise passed to use must be cached or otherwise reused. Creating a new Promise during every render repeatedly suspends the component. A rejected Promise is handled by the nearest Error Boundary, while a pending one activates the nearest Suspense fallback.

Runnable example:

import { Suspense, use } from "react";

const messagePromise = new Promise(resolve =>
  setTimeout(() => resolve("Data loaded"), 700)
);

function Message() {
  return <p>{use(messagePromise)}</p>;
}

export default function App() {
  return (
    <Suspense fallback={<p>Loading…</p>}>
      <Message />
    </Suspense>
  );
}

Common wrong answer: Calling use(fetch("/api/data")) directly during every client render. That creates a fresh Promise instead of reading a stable Suspense-compatible resource.

Likely follow-up question: How should a rejected Promise be presented to the user?

Official React source: use reference.

10. What does <Activity> do in React 19.2?

Level: Mid-level to senior

Short interview answer: <Activity> manages the visibility of a React subtree while preserving its React and DOM state. Hidden content is removed from view, its Effects are cleaned up, and its work may be prepared at a lower priority.

Deeper technical explanation: This is useful for tab interfaces where a draft, scroll position, or expensive subtree should survive temporarily. It isn’t equivalent to ordinary conditional rendering, which destroys the subtree’s state. It also isn’t merely a CSS wrapper: React disconnects Effects when the Activity becomes hidden and reconnects them when visible again.

The DOM remains present, so browser-controlled side effects require care. A hidden <video> element, for example, may continue playing unless cleanup pauses it.

Runnable example:

import { Activity, useState } from "react";

export default function Tabs() {
  const [tab, setTab] = useState("profile");

  return (
    <>
      <button onClick={() => setTab("profile")}>Profile</button>
      <button onClick={() => setTab("notes")}>Notes</button>

      <Activity mode={tab === "profile" ? "visible" : "hidden"}>
        <p>Profile content</p>
      </Activity>
      <Activity mode={tab === "notes" ? "visible" : "hidden"}>
        <textarea defaultValue="Preserved draft" />
      </Activity>
    </>
  );
}

Common wrong answer:<Activity> keeps every Effect running in the background.” Hidden Activity children conceptually unmount their Effects while retaining state.

Likely follow-up question: When would unmounting the component be safer than preserving it?

Official React source: <Activity> reference.

Server Rendering and React Server Components

11. How are React Server Components different from server-side rendering?

Level: Senior

Short interview answer: React Server Components run in a separate build-time or request-time environment and send their rendered output rather than their component JavaScript to the client. Server-side rendering produces initial HTML for a React tree that may still require hydration on the client.

Deeper technical explanation: The technologies can be combined, but they solve different problems. A Server Component may access server-side data and pass serializable values or JSX to a Client Component. Interactivity, state, and browser APIs belong in Client Components.

React 19 stabilizes the Server Component model for application use. However, the underlying APIs used by bundlers and frameworks to implement React Server Components can change between React 19 minor versions. Most teams should therefore use a supported framework rather than inventing an RSC bundler.

Framework-integrated example:

// ProductPage.jsx — Server Component
import AddToCart from "./AddToCart";

export default async function ProductPage({ id }) {
  const product = await database.products.find(id);
  return <AddToCart id={product.id} name={product.name} />;
}
// AddToCart.jsx — Client Component
"use client";

import { useState } from "react";

export default function AddToCart({ id, name }) {
  const [added, setAdded] = useState(false);
  return (
    <button onClick={() => setAdded(true)}>
      {added ? "Added" : `Add ${name}`}
    </button>
  );
}

Common wrong answer: “A Server Component always requires a live Node.js server.” It may run at build time and its output can be served statically.

Likely follow-up question: Why must values passed from a Server Component to a Client Component be serializable?

Official React source: React Server Components.

12. How do Suspense and streaming work together?

Level: Senior

Short interview answer: Suspense divides the UI into boundaries that can show fallbacks independently. During streaming server rendering, React can send the completed shell first and then stream later content as suspended boundaries become ready.

Deeper technical explanation: Suspense doesn’t detect arbitrary fetching performed inside useEffect or an event handler. It works with supported sources such as lazy, a Suspense-integrated framework, or cached Promises read with use. On Node.js, renderToPipeableStream provides streaming output; Web Stream environments use renderToReadableStream.

Once the response has started streaming, some HTTP decisions—especially changing the status code—may be too late. The application must distinguish a shell failure from a recoverable error inside a later boundary.

Runnable Node.js integration:

import { renderToPipeableStream } from "react-dom/server";
import App from "./App";

export function handleRequest(request, response) {
  let failed = false;

  const { pipe } = renderToPipeableStream(<App />, {
    bootstrapScripts: ["/client.js"],
    onShellReady() {
      response.statusCode = failed ? 500 : 200;
      response.setHeader("content-type", "text/html");
      pipe(response);
    },
    onError(error) {
      failed = true;
      console.error(error);
    },
  });
}

Common wrong answer: “Suspense automatically turns every fetch request into streaming data.” The data source or framework must integrate with Suspense.

Likely follow-up question: Where should Error Boundaries be placed relative to Suspense boundaries?

Official React source: renderToPipeableStream and the use documentation.

Performance, Accessibility, and Testing

13. What does React Compiler optimize, and how should performance be measured?

Level: Senior

Short interview answer: React Compiler analyzes components and Hooks at build time and applies automatic memoization where appropriate. It can reduce unnecessary recalculation and rendering, but performance decisions should still be based on measurements rather than assumptions.

Deeper technical explanation: React Compiler 1.0 is stable and can reduce the need for routine useMemo, useCallback, and React.memo. Those APIs remain available as escape hatches. The compiler also relies on the Rules of React; impure rendering and unsafe mutation can prevent correct optimization or expose existing defects.

React 19.2’s Performance Tracks show scheduling priorities, component work, Effects, Suspense activity, and cascading updates in supported browser developer tools. The React DevTools Profiler remains useful for interactive investigation.

Runnable profiling example:

import { Profiler, useState } from "react";

function report(id, phase, actualDuration) {
  console.log({ id, phase, actualDuration });
}

export default function App() {
  const [count, setCount] = useState(0);

  return (
    <Profiler id="Counter" onRender={report}>
      <button onClick={() => setCount(c => c + 1)}>{count}</button>
    </Profiler>
  );
}

Common wrong answer: “Memoization always improves performance.” It has implementation and memory costs, and unnecessary memoization can make code harder to reason about.

Likely follow-up question: How would you distinguish a slow render from a slow Effect or network request?

14. What should a strong React accessibility answer include?

Level: Mid-level

Short interview answer: Accessibility starts with semantic HTML, correct labels, keyboard-operable controls, meaningful focus behavior, and status or error information that assistive technologies can identify. ARIA supplements native semantics; it doesn’t replace them.

Deeper technical explanation: A real <button> already supports keyboard activation and expected browser behavior. A clickable <div> requires developers to recreate semantics and interactions that the browser provides for free. useId is useful for associating fields with descriptions while remaining compatible with multiple component instances and server rendering.

Runnable example:

import { useId, useState } from "react";

export default function EmailField() {
  const hintId = useId();
  const [email, setEmail] = useState("");

  return (
    <div>
      <label>
        Email
        <input
          type="email"
          value={email}
          aria-describedby={hintId}
          onChange={e => setEmail(e.target.value)}
        />
      </label>
      <p id={hintId}>Use the address where you receive work email.</p>
      <button type="button">Verify email</button>
    </div>
  );
}

Common wrong answer: “Add ARIA labels to every element.” Redundant or incorrect ARIA can make an interface less understandable.

Likely follow-up question: How would you manage focus when a modal opens and closes?

Official React source: useId, Responding to Events, and createPortal.

15. What should React component tests verify?

Level: Mid-level

Short interview answer: Component tests should verify observable user behavior: rendered content, accessible controls, interactions, async states, errors, and state transitions. They should avoid depending unnecessarily on private state or internal component structure.

Deeper technical explanation: React’s act helper applies pending updates before assertions. Most testing libraries wrap common render and interaction helpers in act, but understanding it explains why premature assertions become flaky. The async form of act is preferred because React work may cross asynchronous boundaries.

Runnable test example:

import { act } from "react";
import { createRoot } from "react-dom/client";

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

test("increments the visible count", async () => {
  const container = document.createElement("div");
  const root = createRoot(container);

  await act(async () => root.render(<Counter />));
  await act(async () => container.querySelector("button").click());

  expect(container.textContent).toBe("1");
});

Common wrong answer: “A large snapshot proves the component works.” Snapshots can detect output changes, but they rarely prove that interactions, accessibility, and async behavior are correct.

Likely follow-up question: What belongs in a unit test, an integration test, and an end-to-end test?

Official React source: act testing helper.

Upgrading from React 18 to React 19

16. How would you plan a React 18-to-19 migration?

Level: Senior

Short interview answer: Upgrade in controlled stages: remove existing warnings, adopt React 18.3 as a diagnostic step where practical, verify the modern JSX transform, run the official codemods, update React and TypeScript types together, and test critical flows under Strict Mode before production rollout.

Deeper technical explanation: React 19 removes or changes several deprecated APIs and TypeScript behaviors. Library compatibility matters as much as application code, so check routers, component libraries, testing tools, SSR infrastructure, and framework requirements. The migration should be separated from unrelated feature work and validated through automated tests, browser checks, performance measurements, and production monitoring.

React 19 also allows ref to be passed as a prop to function components, reducing the need for forwardRef in new code.

Runnable React 19 example:

import { useRef } from "react";

function SearchInput({ ref }) {
  return <input ref={ref} placeholder="Search" />;
}

export default function App() {
  const inputRef = useRef(null);

  return (
    <>
      <SearchInput ref={inputRef} />
      <button onClick={() => inputRef.current?.focus()}>Focus</button>
    </>
  );
}

Common wrong answer: “Change the package version, fix compilation errors, and deploy.” Compilation cannot detect every behavioral, Effect-cleanup, hydration, dependency, or third-party compatibility problem.

Likely follow-up question: Which removed APIs and TypeScript changes would you search for before upgrading?

Frequently asked questions (FAQ)

Which React version should I prepare for a 2026 interview?

Prepare React 19.2 concepts, but remain comfortable reading and maintaining React 18 code. Many production applications upgrade gradually, so an interviewer may test modern APIs while using an older codebase in the exercise.

Be ready to explain which behavior belongs to React 19 and which patterns remain version-independent. If a company specifies its stack in the job description, prioritise that version rather than forcing newer APIs into every answer.

How much JavaScript should I know before attempting React interview questions?

You need a dependable understanding of JavaScript functions, closures, promises, modules, array methods, object immutability, event propagation, and asynchronous execution. Weak JavaScript knowledge often appears as a React problem when the actual difficulty is stale closures, reference equality, or Promise handling.

For example, understanding why setItems([...items, newItem]) creates a new array is more useful than merely memorising that React state should be immutable.

Are class components still worth preparing for React interviews?

Learn enough class-component syntax to maintain existing applications and translate lifecycle methods into modern patterns. You should recognise componentDidMount, componentDidUpdate, componentWillUnmount, setState, and shouldComponentUpdate, even if the role primarily uses function components.

Class components also remain relevant when discussing traditional Error Boundaries. You probably don’t need to build every coding-round solution with classes unless the interviewer requests it or the company maintains a class-heavy codebase.

Should I use TypeScript in a React coding interview?

Use TypeScript when the role expects it and you can write it confidently without slowing down the solution. Clear prop types, event types, discriminated unions, and reducer actions can demonstrate useful engineering judgement.

JavaScript is preferable to incorrect or unnecessarily elaborate TypeScript. During a timed exercise, explain your choice briefly. A working, accessible component with sensible state ownership is usually stronger than an unfinished solution containing complex generic types.

Do I need to memorise every React 19 API?

No. Interviewers gain more information from your mental model than from a complete API inventory. Prioritise state identity, rendering, Effects, events, Suspense, async mutations, server and client boundaries, performance diagnosis, and accessibility.

For less familiar APIs, explain their purpose and constraints accurately. Saying that useEffectEvent separates non-reactive Effect logic is stronger than recalling its signature while using it to conceal missing dependencies.

How should I answer a question about a React feature I haven’t used in production?

State that limitation honestly, then explain what you understand and how you would validate it. Distinguish documented behavior from assumptions and avoid inventing project experience.

A useful response might explain that you haven’t deployed <Activity>, but understand that it preserves React and DOM state while disconnecting Effects when hidden. You can then describe the test you would run, such as checking preserved form input, subscription cleanup, and media behavior when switching tabs.

What kind of project is best for React interview preparation?

Choose a small application with enough interaction to expose engineering decisions. A task manager, booking flow, support dashboard, or product search interface can demonstrate form handling, async states, routing, accessibility, testing, error recovery, and performance measurement.

Depth matters more than screen count. One completed workflow that handles loading, empty, success, validation, failure, and retry states gives you more useful interview material than several visually polished pages backed by static data.

How should state-management choices be explained in a system-design round?

Start by identifying who owns each piece of state, how frequently it changes, and which parts of the tree consume it. Keep temporary interface state close to the component, lift shared state to the nearest common owner, and introduce external state management only when the application’s coordination needs justify it.

The important trade-off is update scope and operational clarity. Context may suit authentication or theme data, while a larger transactional workflow may benefit from reducers, a dedicated store, server-state tooling, or a combination.

What should I do if a React coding exercise re-renders too often?

Measure before adding memoization. Use React DevTools, the Profiler, or React Performance Tracks to identify which component renders, what triggered it, and whether the render is actually expensive.

Common causes include state being placed too high, Effects that schedule cascading updates, unstable object or function props, and context values recreated on every render. Fix the ownership or update pattern first. Apply manual memoization only when measurement shows that repeated work is meaningful and the optimization remains understandable.

Which mistakes weaken otherwise correct React interview answers?

Outdated certainty is a frequent problem. Examples include claiming that SyntheticEvents are still pooled, describing every Effect as a lifecycle callback, treating Suspense as a detector for arbitrary fetch requests, or presenting Server Components as identical to server-side rendering.

Another warning sign is prescribing one tool universally. Strong answers establish conditions: stable IDs versus array indexes, local state versus a shared store, controlled versus uncontrolled inputs, and compiler optimization versus manual memoization. The trade-off often matters more than the chosen API.

How should I prepare for React accessibility and testing questions?

Practise building and testing the same interaction from a user’s perspective. Use semantic controls, connected labels, keyboard navigation, visible focus, understandable errors, and appropriate status announcements. Then verify the behavior through DOM-based tests rather than private component state.

For example, test that submitting an invalid form exposes an associated error and moves focus appropriately. That demonstrates more practical understanding than asserting that an internal isValid variable changed.

Is React knowledge alone enough for a senior front-end interview?

Usually not. Senior roles commonly require browser fundamentals, JavaScript and TypeScript, HTTP behavior, security, accessibility, testing strategy, performance analysis, build and deployment awareness, and architectural communication alongside React.

React should be presented as one part of the system. A senior candidate should be able to explain what runs in the browser, what belongs on the server, how failures are observed, how changes are released safely, and why the selected architecture fits the product’s scale and team.

What to Practise Before the Interview

Start by running every example and changing one condition. Replace stable list IDs with indexes and reorder the data. Remove an Effect cleanup and observe Strict Mode. Create a fresh Promise inside a component that calls use. Hide a video inside <Activity>. These small experiments expose the difference between recognising an API and understanding its lifecycle.

Next, practise answering each question in roughly 30 seconds. State the rule, explain when it matters, and name one common failure. For senior interviews, add the validation method: a test, profiler trace, accessibility check, migration stage, or production metric.

The 2026 React interview boundary is clear. Fundamentals still matter, but a current candidate should also understand React 19 Actions, use, useEffectEvent, <Activity>, React Server Components, Suspense streaming, React Compiler, and evidence-based performance work. Learn the relationships between those features rather than treating them as isolated vocabulary.

If this saved you some time, the comment section below is the nicest way to say hi 👋
Ankit Khoiwal

Ankit Khoiwal

Wrote this one

I write from Udaipur. The code in this post ran on my machine first - web, mobile, backend, whichever stack this one needed.

Related Posts
React Interview Questions and Answers for Freshers

React Interview Questions and Answers for Freshers

Prepare for React interview questions for freshers with React 19.2 explanations, coding exercises and common mistakes. Get a focused 2026 study plan.

Read Full Story
Next.js 16.3 Guide for React Developers

Next.js 16.3 Guide for React Developers

Next.js 16.3 guide for React developers covering App Router, caching, Turbopack, routing, images, and deployment limits. See practical examples.

Read Full Story
Next.js Hydration Errors Explained: Fixes and suppressHydrationWarning (2026)

Next.js Hydration Errors Explained: Fixes and suppressHydrationWarning (2026)

Tired of hydration warnings? Learn why server and client HTML differ and how to fix dates, themes, client-only code, and UI libs in 2026.

Read Full Story