React Interview Questions: 23 Answers on Hooks, React 19 & Coding

23 React interview questions with sample answers: keys, useEffect cleanup, React.memo, Context vs Redux, React 19 Actions, Server Components and live coding.

By OphyAI Team • • Updated November 13, 2026 • 5599 words

Last updated: November 2026

Quick Answer

React interviewers test whether you understand how React decides what to render and when: state as a snapshot, the effect lifecycle and its cleanup, why keys and stable references matter for re-renders, where state should live, and what React 18 and 19 changed (concurrent rendering, Actions, Server Components). Rehearse the spoken answers in OphyAI Interview Practice, and use OphyAI Coding Copilot for the live coding round. Expect a block of concept questions plus one small component built live, often a search box or a todo list.

#QuestionWhat it tests
1What JSX compiles toMental model of elements
2Virtual DOM and reconciliationHow updates reach the DOM
3Why lists need keysIdentity across renders
4Props vs stateData ownership
5Why state does not update immediatelyState as a snapshot
6useEffect dependencies and cleanupEffect lifecycle
7Effects running twice in developmentStrict Mode
8useMemo vs useCallbackReferential stability
9useRef vs stateValues that do not render
10Rules of hooksHow hooks are tracked

The Questions, With Sample Answers

1. “What is JSX, and what does it compile to?”

Why they ask. It checks whether you see components as functions that return plain objects, which every later answer depends on.

Sample answer. “JSX is a syntax extension that lets me write markup inside JavaScript. It is not HTML: a compiler such as Babel, SWC or esbuild turns each tag into a function call. With the modern automatic runtime that is a call to jsx() from react/jsx-runtime; in older setups it was React.createElement. The call returns a React element, a lightweight object describing the type, props and children. Because JSX is an expression, I can map over arrays, use ternaries and pass elements as props. The differences from HTML follow from that: className instead of class, htmlFor instead of for, camelCase event handlers, and curly braces for any JavaScript value. Elements are immutable descriptions; React decides later what to do with them.”

Weak answers. “JSX is HTML in JavaScript”, or not knowing a build step is involved.

2. “What is the virtual DOM, and how does reconciliation work?”

Why they ask. It is the classic opener, and the follow-up (“so why do keys matter?”) shows whether you understand it or memorized it.

Sample answer. “When state changes, React calls my component again and gets a new tree of elements. Reconciliation compares that tree with the previous one and works out the minimum set of DOM changes to commit. A full tree diff would be too slow, so React uses two heuristics. First, if an element’s type changes, say a div becomes a section or one component becomes another, React throws away that subtree and its state and builds a new one. Second, among siblings, keys tell React which child is which across renders. Rendering and committing are separate phases: render is calling components, commit is touching the DOM. The point is not that a virtual DOM is magically fast; it is that I describe the UI declaratively and React handles the updates.”

Weak answers. Claiming the virtual DOM is always faster than direct DOM work, or skipping the type and key rules.

3. “Why does React need keys when rendering lists?”

Why they ask. Index-as-key bugs are among the most common real React bugs, and interviewers love them.

Sample answer. “A key gives each list item a stable identity, so React can match items between renders even after inserts, deletes or reorders. Keys must be unique among siblings and must not change between renders, which is why I use an ID from the data, like a database ID. Using the array index works only if the list never reorders or filters; otherwise state can attach to the wrong row, for example a checked checkbox or typed input jumping to a different item after a deletion. Generating keys during render with Math.random() is worse: keys never match, so React recreates every item and its DOM on every render and loses input state. Keys are not passed to the component as a prop, so if the child needs the ID I pass it separately.”

Weak answers. “Keys silence the console warning”, or reaching for key={index} by default.

Rehearse the reconciliation and keys follow-ups out loud with a mock interviewer in Interview Practice, which asks the second “why?” for you.

4. “What is the difference between props and state?”

Why they ask. It is a fast check of data ownership, and the best candidates go beyond the textbook line.

Sample answer. “Props are inputs a parent passes to a child; the child treats them as read-only. State is memory a component owns and changes over time with a setter, which triggers a re-render. The interesting part is deciding which is which. If a value can be computed from props or other state, it should not be state at all; I derive it during render. If two siblings need the same value, the state moves up to their closest common parent and flows down as props. A common bug is copying a prop into state with useState(props.value), because the state ignores later prop changes. When I need a reset, I give the child a key so React remounts it.”

Weak answers. Stopping at “props are immutable, state is mutable” with nothing about derived values or where state lives.

5. “Why doesn’t my state update immediately after I call setState?”

Why they ask. The stale-value surprise is the most common hooks misunderstanding.

Sample answer. “State behaves like a snapshot. During a render, count is a constant for that render; calling setCount asks React to render again with a new value, but the variable in the current closure does not change. So if I call setCount(count + 1) three times in one handler, all three read the same count and the result goes up by one. When the next value depends on the previous one, I pass an updater function, setCount(c => c + 1), and React queues the updaters and applies them in order. React also batches the updates from one event into a single re-render, so I see one render, not three.”

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

Weak answers. “setState is async”, with no explanation of closures or updater functions.

6. “How do useEffect dependencies and cleanup work?”

Why they ask. Effects cause the most production bugs: infinite loops, stale data, leaked subscriptions and race conditions.

Sample answer. “An effect synchronizes the component with something outside React, like a subscription, a timer or a network request. The dependency array lists every reactive value the effect reads. With a list, the effect runs after the first commit and after any commit where a dependency changed, compared with Object.is. With an empty array it runs once after mount; with no array it runs after every commit. The cleanup function runs before the effect re-runs with new values and when the component unmounts. For fetching, I use cleanup to ignore or abort stale responses, so a slow reply for the old ID cannot overwrite the new one. I keep the lint rule on rather than leaving dependencies out to stop a loop.”

useEffect(() => {
  let ignore = false;
  fetchUser(userId).then((user) => {
    if (!ignore) setUser(user);
  });
  return () => {
    ignore = true;
  };
}, [userId]);

Weak answers. Describing effects as “componentDidMount for hooks”, or disabling the exhaustive-deps rule.

7. “Why does my effect run twice in development?”

Why they ask. Almost every React developer has hit this, and the right answer shows you understand what cleanup is for.

Sample answer. “That is Strict Mode. In development only, React runs one extra setup and cleanup cycle when a component first mounts, so the sequence is setup, cleanup, setup. It is a stress test: if my cleanup does not fully undo what setup did, the double run exposes it, for example two open connections or a doubled event listener. Production runs the effect once. The fix is never to block the second run with a ref flag; it is to write a proper cleanup that closes the connection or removes the listener. For data fetching, the ignore flag or an AbortController makes the double request harmless, and a data library with a cache avoids the duplicate entirely.”

Weak answers. “It is a React bug”, or “turn off Strict Mode”.

8. “What is the difference between useMemo and useCallback, and when do you use them?”

Why they ask. Over-memoizing is common, and interviewers want to hear judgment rather than habit.

Sample answer. “useMemo caches the result of a calculation between renders until its dependencies change. useCallback caches a function itself; useCallback(fn, deps) is the same as useMemo(() => fn, deps). I use them for two reasons: to skip a genuinely expensive computation, like filtering thousands of rows, and to keep a reference stable when it goes to a memoized child or into another hook’s dependency array. I do not wrap everything, because memoization has its own cost and makes code harder to read. I measure first with the React DevTools Profiler. I also mention React Compiler, which reached 1.0 in October 2025 and memoizes components and values automatically, so in a compiled codebase most manual useMemo and useCallback calls become unnecessary.”

Weak answers. “useCallback makes functions faster”, or memoizing every handler without a reason.

9. “What is useRef for, and how is it different from state?”

Why they ask. It tests whether you know which values should and should not trigger renders.

Sample answer. “useRef returns a mutable object with a current property that keeps its value across renders. Changing current does not re-render the component, which is the key difference from state. I use refs for two things: holding a DOM node, for example to focus an input or measure an element, and holding values that matter to logic but not to the UI, like a timer ID or the latest value for a callback. I avoid reading or writing ref.current during render, because that makes the output depend on something React does not track. In React 19, function components can accept ref as a regular prop, so new components no longer need forwardRef.”

Weak answers. Using a ref to store something displayed on screen and wondering why the UI does not update.

10. “What are the rules of hooks, and why do they exist?”

Why they ask. The rules look arbitrary until you understand how React tracks hook state.

Sample answer. “Call hooks only at the top level of a function component or a custom hook, never inside conditions, loops or nested functions, and never from regular JavaScript functions. The reason is that React identifies each hook by the order of calls during a render. If a useState sits inside an if, the order can change between renders and React hands the wrong state to the wrong hook. The eslint-plugin-react-hooks package enforces this, and I keep it on. One exception worth knowing: the React 19 use API can be called conditionally, because it reads a promise or context rather than storing state at a fixed slot.”

Weak answers. Reciting the rules without the call-order reason.

Practice the hooks block as a timed spoken round in Interview Practice; these answers fall apart when an interviewer asks for an example from your own code.

11. “When would you write a custom hook?”

Why they ask. It shows whether you can share logic without inheritance or wrapper components.

Sample answer. “A custom hook is a function whose name starts with use and that calls other hooks. I write one when two components repeat the same stateful logic, like subscribing to window size, reading from local storage or debouncing a value. Each component that calls the hook gets its own independent state; hooks share logic, not state. If I want components to share the same state, I need Context or a store instead. A good custom hook has a small, purpose-named API, like useOnlineStatus() returning a boolean, rather than a generic useEffectOnce that hides what it does.”

Weak answers. Believing two components using the same hook share its state.

12. “What causes a component to re-render?”

Why they ask. Performance questions start here, and many candidates think props changes are the trigger.

Sample answer. “A component re-renders in three cases: its own state changes, its parent re-renders, or a context it reads changes. A prop changing is not a trigger on its own; the child re-renders because the parent did. By default, when a parent renders, all its children render too, whether or not their props changed. Re-rendering is usually cheap, because rendering just calls functions and React only touches the DOM where output differs. When it does matter, I profile with React DevTools to find the expensive subtree, then move state down closer to where it is used, pass children as props so they are not re-created, or memoize the slow child.”

Weak answers. “Components re-render when props change”, with no mention of parents or context.

13. “When should you use React.memo?”

Why they ask. It follows directly from the last question and tests whether you know memo’s limits.

Sample answer. “React.memo wraps a component so it skips re-rendering when its props are shallowly equal to last time, compared with Object.is. It is useful for a component that renders often with the same props and is expensive to render, like a chart or a large row. It has limits: the component still re-renders when its own state or a context it uses changes, and an inline object or arrow function prop is a new reference every render, so memo does nothing unless I stabilize those with useMemo or useCallback. The React docs call memoization a performance optimization, not a guarantee. With React Compiler enabled, the compiler applies the equivalent automatically, so I would rarely add memo by hand.”

Weak answers. Wrapping every component in memo, or not knowing that inline objects defeat it.

14. “How would you render a list of 10,000 rows?”

Why they ask. It moves from React APIs to real front-end performance.

Sample answer. “First I ask whether the user needs all 10,000 at once; pagination or infinite loading may solve it. If they do, I virtualize: render only the rows in the viewport plus a small buffer, using a library such as react-window or TanStack Virtual, so the DOM holds dozens of nodes instead of thousands. Each row gets a stable key from the data. I memoize the row component and keep its props stable so scrolling does not re-render every row. Filtering and sorting happen in a memoized computation, and if typing in a filter box feels slow, I mark the list update as a transition or use useDeferredValue so the input stays responsive.”

Weak answers. Jumping straight to memo without reducing the number of DOM nodes.

For the performance block, a timed mock in Interview Practice helps you practice the order that scores well: measure, then fix.

15. “How do code splitting and Suspense work in React?”

Why they ask. Bundle size is a front-end interview staple, and Suspense now covers data as well as code.

Sample answer. “Code splitting loads parts of the app only when needed. In React I use lazy with a dynamic import, which the bundler turns into a separate chunk, and wrap the lazy component in Suspense with a fallback that shows while the chunk loads. Route-level splitting is the usual first win, then heavy widgets like editors or charts. lazy expects the module to have a default export. Suspense is more general than code: any component that suspends, such as one reading a promise with use or a data library integrated with Suspense, shows the nearest fallback. Inside a transition, React keeps the already visible content instead of flashing back to the fallback.”

import { lazy, Suspense } from 'react';

const Settings = lazy(() => import('./Settings'));

function App() {
  return (
    <Suspense fallback={<p>Loading...</p>}>
      <Settings />
    </Suspense>
  );
}

Weak answers. Not knowing that lazy needs a Suspense boundary above it.

16. “How do you choose between lifting state, Context, and a store like Redux or Zustand?”

Why they ask. Architecture judgment separates mid-level from senior front-end candidates.

Sample answer. “I start with the simplest option. Local state stays in the component. Shared state between siblings moves up to the closest common parent. Context fits values that many components read and that change rarely, like the theme, locale or signed-in user, because every consumer re-renders when the value changes. For frequently changing client state used across the app, a store helps: Redux Toolkit gives a single store, predictable reducers, middleware and strong DevTools, at the cost of more structure; Zustand is a smaller hook-based store where components subscribe to slices, with less ceremony. Server data is a separate category, and I keep it in a fetching library like TanStack Query or the framework’s data layer rather than in a global store.”

Weak answers. “Always use Redux”, or treating Context as a high-frequency state manager.

17. “What changed in React 18: concurrent rendering and automatic batching?”

Why they ask. Many codebases upgraded, and interviewers check that you know what actually changed.

Sample answer. “React 18, released in March 2022, introduced concurrent rendering, which makes rendering interruptible: React can start a render, pause it for more urgent work and resume or throw it away, while keeping the UI consistent. It is opt-in through features like transitions. Apps get it by moving to createRoot. React 18 also added automatic batching. Before, React batched state updates only inside its own event handlers; updates in promises, timeouts or native event listeners each caused a render. Now those are batched too, so two setters in a setTimeout produce one render. If I truly need a synchronous update, flushSync opts out. Strict Mode also gained the development-only remount check.”

Weak answers. Saying concurrent rendering means multithreading, or that it is always on.

18. “What do useTransition and useDeferredValue do?”

Why they ask. It tests whether you can apply concurrent features to a real lag problem.

Sample answer. “Both mark work as non-urgent so urgent updates, like typing, stay responsive. useTransition returns isPending and a startTransition function; state updates inside startTransition are low priority and can be interrupted by a keystroke, and isPending lets me show a subtle loading state. Since React 19, the function I pass can be async, which is the basis of Actions. One limit: a transition cannot control a text input, because the input must update synchronously. So I keep the input value in normal state and either put the expensive update in a transition or use useDeferredValue on the query, which gives me a version of the value that lags behind during heavy renders.”

const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
// <input value={query} onChange={(e) => setQuery(e.target.value)} />
// <SlowResults query={deferredQuery} />

Weak answers. Wrapping the input’s own setValue in startTransition.

19. “What are React Server Components, and how are they different from SSR?”

Why they ask. Next.js App Router made Server Components standard in many teams, and the terms are often confused.

Sample answer. “Server Components render ahead of time, before bundling, in an environment separate from the browser, either at build time or per request. Their code never ships to the client, so they can be async and read a database or file system directly, and they add nothing to the bundle. They cannot use state, effects or browser APIs. For interactivity I import a Client Component, marked with the 'use client' directive, and pass it data or JSX as props. There is no directive for Server Components; 'use server' marks Server Functions. SSR is different: it renders Client Components to HTML on the server for the first paint, then the browser downloads their JavaScript and hydrates. The two work together in frameworks like Next.js.”

Weak answers. Calling Server Components “just SSR”, or saying 'use server' marks a Server Component.

20. “What are Actions and the use API in React 19?”

Why they ask. React 19 has been stable since December 5, 2024, and it is the newest material interviewers expect you to know.

Sample answer. “Actions are async functions used in transitions. React tracks their pending state, errors and optimistic updates for me, and forms can take a function as their action prop, after which React resets uncontrolled fields on success. useActionState wraps an Action and returns its last result, the wrapped Action and a pending flag; useFormStatus lets a submit button read its parent form’s pending state; useOptimistic shows the expected result while the request is in flight. The use API reads a promise or a context during render. With a promise it suspends until it resolves, and unlike hooks it can be called conditionally. It does not support promises created during render; those should come from a framework or cache.”

import { useActionState } from 'react';

function UpdateName() {
  const [error, submitAction, isPending] = useActionState(
    async (previousState, formData) => {
      const err = await updateName(formData.get('name'));
      return err ?? null;
    },
    null,
  );
  return (
    <form action={submitAction}>
      <input type="text" name="name" />
      <button type="submit" disabled={isPending}>Update</button>
      {error && <p>{error}</p>}
    </form>
  );
}

Weak answers. Not having heard of Actions, or confusing use with a general-purpose hook.

21. “How do you test React components?”

Why they ask. Teams want engineers who test behavior, not implementation details.

Sample answer. “I use React Testing Library with Jest or Vitest. Its principle is that tests should resemble how users interact with the UI, so I render the component, find elements the way a user or screen reader would, interact, then assert on what is visible. The query priority starts with getByRole, then labels and text, with getByTestId as a last resort. getBy throws if nothing matches, queryBy returns null so I can assert something is absent, and findBy returns a promise for content that appears asynchronously. For interactions I use user-event, and for network calls I mock at the request level, for example with Mock Service Worker, rather than mocking hooks.”

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Counter from './Counter';

test('increments the count', async () => {
  const user = userEvent.setup();
  render(<Counter />);
  await user.click(screen.getByRole('button', { name: /count/i }));
  expect(screen.getByRole('button')).toHaveTextContent('Count: 3');
});

Weak answers. Testing internal state or snapshotting everything. (toHaveTextContent comes from @testing-library/jest-dom.)

22. Live coding: “Build a search box that debounces the API call.”

Why they ask. It combines a custom hook, effect cleanup and race conditions in one short exercise.

Sample answer. “I would split it into a reusable useDebouncedValue hook and the component. The hook sets a timeout when the value changes and clears it in cleanup, so only the last value after a pause gets through. The component fetches when the debounced query changes and aborts the previous request in cleanup, so an old, slow response cannot overwrite a newer one. With more time I would add loading and error states and caching. I would also say the delay, here 300 ms, is a product choice I would confirm.”

import { useEffect, useState } from 'react';

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

export default function Search() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  const debouncedQuery = useDebouncedValue(query, 300);

  useEffect(() => {
    if (!debouncedQuery) {
      setResults([]);
      return;
    }
    const controller = new AbortController();
    fetch(`/api/search?q=${encodeURIComponent(debouncedQuery)}`, {
      signal: controller.signal,
    })
      .then((res) => res.json())
      .then(setResults)
      .catch((err) => {
        if (err.name !== 'AbortError') console.error(err);
      });
    return () => controller.abort();
  }, [debouncedQuery]);

  return (
    <>
      <input
        aria-label="Search"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
      />
      <ul>
        {results.map((r) => (
          <li key={r.id}>{r.name}</li>
        ))}
      </ul>
    </>
  );
}

Weak answers. Debouncing inside the render body, forgetting clearTimeout, or ignoring out-of-order responses.

Prepare for the live coding round with Coding Copilot: each answer card shows how it read the problem, what to say first, the code, a dry run with edge cases and the Big O.

23. Live coding: “Build a todo list with an All / Active / Done filter.”

Why they ask. It shows immutable updates, derived state and clean component structure.

Sample answer. “I keep two pieces of state, the todos array and the current filter, and derive the visible list during render instead of storing it, so it can never drift out of sync. Updates are immutable: adding spreads into a new array, toggling maps to a new object for the matching ID. Each todo gets a stable ID, so keys survive filtering. The form uses onSubmit so Enter works, and it ignores blank input. If the list grew large I would memoize the filtered result, and with more time I would extract TodoItem, add delete and editing, and persist to local storage through a custom hook.”

import { useState } from 'react';

const FILTERS = {
  all: () => true,
  active: (todo) => !todo.done,
  done: (todo) => todo.done,
};

export default function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [text, setText] = useState('');
  const [filter, setFilter] = useState('all');

  function addTodo(e) {
    e.preventDefault();
    const trimmed = text.trim();
    if (!trimmed) return;
    setTodos((prev) => [...prev, { id: crypto.randomUUID(), text: trimmed, done: false }]);
    setText('');
  }

  function toggle(id) {
    setTodos((prev) => prev.map((t) => (t.id === id ? { ...t, done: !t.done } : t)));
  }

  const visible = todos.filter(FILTERS[filter]);

  return (
    <div>
      <form onSubmit={addTodo}>
        <input aria-label="New todo" value={text} onChange={(e) => setText(e.target.value)} />
        <button type="submit">Add</button>
      </form>
      {Object.keys(FILTERS).map((name) => (
        <button key={name} onClick={() => setFilter(name)} aria-pressed={filter === name}>
          {name}
        </button>
      ))}
      <ul>
        {visible.map((t) => (
          <li key={t.id}>
            <label>
              <input type="checkbox" checked={t.done} onChange={() => toggle(t.id)} />
              {t.text}
            </label>
          </li>
        ))}
      </ul>
    </div>
  );
}

Weak answers. Mutating the array with push, storing the filtered list in its own state, or using the index as the key.

How to Practice These

Run a voice or text mock in OphyAI Interview Practice, which asks follow-up questions and gives a transcript and per-answer feedback, so you can test whether your useEffect or reconciliation answer survives a second question. For the live coding round, Coding Copilot in the desktop app (Premium plan, 15 credits a session) snaps the problem window with Cmd/Ctrl+Shift+A and returns the approach, code, a dry run and the Big O in an overlay left out of screen sharing. For the conversational rounds, OphyAI Interview Copilot gives real-time answer suggestions on Zoom, Microsoft Teams and Google Meet. Start practicing →

A simple routine: answer five concept questions aloud each day in under two minutes each, then build one small component from scratch in a plain editor with a 25-minute timer. If your loop also has an algorithm round, see the technical interview prep guide for software engineers and our coding interview patterns page.

Frequently Asked Questions

What React topics come up most in interviews?

Interview guides and candidate reports most often cover state and props, the useState snapshot behavior, useEffect dependencies and cleanup, keys and reconciliation, memoization with useMemo, useCallback and React.memo, Context versus a store, and testing. Senior loops add architecture, performance profiling, Server Components and the React 18 and 19 features, plus one live component build.

Which React version should I prepare for?

Prepare for React 19, which has been stable since December 5, 2024, with 19.2 in October 2025 and 19.3 in September 2026 per the react.dev versions page. Know hooks deeply, plus the React 18 concurrency features, Actions, the use API and Server Components. Class components still appear in older codebases, so be ready to read lifecycle methods, but few interviews ask you to write them.

Do React interviews still ask about class components?

Some do, mostly at companies with older codebases. Expect to explain how componentDidMount, componentDidUpdate and componentWillUnmount map to effects, and why error boundaries still use class components. Most new code and most interview questions use function components and hooks, so spend the bulk of your time there and treat classes as reading knowledge.

Should I learn Next.js for a React interview?

If the job description mentions Next.js, yes: know the App Router, Server Components, the 'use client' boundary, data fetching and caching. React’s own docs recommend starting new apps with a framework, and Create React App was sunset in February 2025. For a pure React role, framework knowledge is a plus but the questions above matter more.

How do I answer React questions without sounding memorized?

Give a one-sentence definition, then an example from code you shipped, then a trade-off or bug it caused. For example, explain effect cleanup, describe a stale-fetch bug you fixed with an AbortController, then mention how Strict Mode exposed it. Interviewers dig into your example, so pick one you can discuss for two minutes.

How long does it take to prepare for a React interview?

If you write React daily, one to two weeks of focused review on hooks, rendering and the newer APIs, plus three or four timed component builds, is a common plan. If you are coming from another framework, allow three to four weeks. These are typical ranges from prep guides, not a rule; adjust for seniority and the number of rounds.

How does OphyAI work in a React coding interview?

Rehearse the spoken questions, such as reconciliation or effect cleanup, in Interview Practice. For the live build, Coding Copilot in the desktop app reads the problem from your screen with Cmd/Ctrl+Shift+A, or transcribes a question the interviewer asks aloud when you press Space or Cmd/Ctrl+Shift+L, and follow-ups remember the problem. Its overlay is left out of screen sharing, though not out of a webcam, keystroke and paste history, tab or focus tracking, or proctoring software.

Sources and verification notes

Sources checked November 2026 by fetching each page. API behavior in the sample answers follows the official React documentation; the questions are original templates based on common interview topics, not questions published by any employer.

  • React blog, React v19: stable release December 5, 2024; Actions, useActionState, useFormStatus, useOptimistic, the use API (callable conditionally, no promises created in render), ref as a prop, Server Components and Server Actions.
  • React blog, React v18.0: March 29, 2022; concurrent rendering is interruptible and opt-in, automatic batching of updates in promises and timeouts, transitions, and the development-only Strict Mode remount.
  • React docs, useEffect: dependency comparison with Object.is, cleanup timing, the extra development-only setup and cleanup cycle, and the ignore flag for fetch race conditions.
  • React docs, Rendering Lists: key rules, index and Math.random() keys, and keys not being passed as props.
  • React docs, memo: shallow comparison with Object.is, memoization as an optimization rather than a guarantee, and React Compiler applying it automatically.
  • React docs, useTransition: return values, async functions in startTransition, and transitions not controlling text inputs.
  • React docs, Server Components: no directive for Server Components, 'use client', async components, and no useState on the server.
  • React versions and React 19.2 post: 19.2 on October 1, 2025 with Activity and useEffectEvent; 19.3 on September 9, 2026; React Compiler v1.0 on October 7, 2025.
  • React blog, Sunsetting Create React App: February 14, 2025; new apps are pointed to frameworks or build tools.
  • Testing Library, About Queries: the guiding principle, query priority and getBy / queryBy / findBy behavior.

Tags:

react interview questions frontend interview javascript interview react hooks coding interview

Coding round coming up? Coding Copilot reads the problem with one hotkey.

In the OphyAI desktop app, Coding Copilot snaps the problem on your screen and returns an approach, working code, edge cases and the Big O, in an overlay left out of screen sharing. It is part of the Premium plan.

Hidden from screen share and recording; a webcam or a person in the room can still see your screen, and the overlay never takes focus from your editor.