React Interview Mock sample questions with answers

10 questions from the React Interview Mock practice bank, spread across its domains. Pick your answer, then open the explanation to see why each option is right or wrong.

  1. Question 1State and Hooks

    What does this counter show after five seconds?

    function Counter() {
      const [count, setCount] = useState(0);
      useEffect(() => {
        const id = setInterval(() => setCount(count + 1), 1000);
        return () => clearInterval(id);
      }, []);
      return <p>{count}</p>;
    }
    • A

      1

    • B

      5

    • C

      0, because an effect with an empty dependency list never starts the interval

    • D

      It counts up, but resets to 0 every second because the interval restarts

    Show the answer and explanation

    Answer: A

    The callback closes over count from the render that created it: 0. Every tick sets the state to 1, which React ignores after the first time. Fix it with setCount(c => c + 1), or with Dan Abramov's useInterval, which stores the latest callback in a ref so the interval never restarts but always calls fresh code.

    Why the other options are wrong

    • B. That needs a functional update (c => c + 1) or a callback that sees the latest count.

    • C. An effect with [] runs once after mount, so the interval does start.

    • D. The deps are [], so the interval is never restarted.

  2. Question 2Architecture and Modern React

    A layout wants every component below it to read the current theme. A teammate writes const theme = useContext(ThemeContext) inside an async Server Component, and it errors. Which two changes are valid fixes? (Choose two.)

    Choose 2.

    • A

      Create a 'use client' ThemeProvider that renders the context provider around {children}

    • B

      Read the theme with useContext in a Client Component somewhere below that provider

    • C

      Mark the async Server Component with 'use server' so it is allowed to call hooks

    • D

      Wrap the useContext call in React.cache() so it runs once per request

    • E

      Call React.createContext inside the Server Component so each request gets its own context

    Show the answer and explanation

    Answer: A and B

    React context is not available in Server Components. The standard pattern is a small Client Component provider (for example ThemeProvider) that the server layout renders around {children}. Server Components inside still render on the server, and any Client Component below the provider can read the value with useContext. To share data between Server Components, use props or cache().

    Why the other options are wrong

    • C. 'use server' marks Server Functions; it never enables hooks in components.

    • D. cache memoises data functions and does not make context available on the server.

    • E. Creating context in a Server Component does not help; it still cannot read context.

  3. Question 3Components and Rendering

    A Vite + React project uses CSS Modules with Vite's default settings. The stylesheet defines .btn-primary { … }, but the button below gets no class. Why?

    import styles from './Button.module.css';
    
    export function Button() {
      return <button className={styles.btnPrimary}>Save</button>;
    }
    • A

      CSS Modules only work with Tailwind, so the import is ignored

    • B

      Keys keep their original names, so read styles['btn-primary'] instead

    • C

      CSS Modules scope classes to one file, so .btn-primary must be marked :global

    • D

      Vite inlines module classes at build time, so they only work in production

    Show the answer and explanation

    Answer: B

    A CSS Module turns each class into a unique, hashed name and exports a mapping object. By default Vite exports the original class names unchanged, so a kebab-case class must be read as styles['btn-primary']. styles.btnPrimary is undefined, and React renders no class at all. Set css.modules.localsConvention: 'camelCaseOnly' if you prefer camelCase keys. Checked against Vite 8.3, which passes localsConvention through unset by default.

    Why the other options are wrong

    • A. CSS Modules work with plain CSS files named *.module.css.

    • C. Local scoping is the point; the generated name is exported for you to use.

    • D. CSS Modules work the same way in dev and production builds.

  4. Question 4Performance and Concurrency

    A component assigns IDs with a module-level counter during render: let next = 0; function Row() { const id = next++; ... }. In production the IDs sometimes skip numbers, and in development every ID is off by one. Why?

    • A

      The counter is shared between browser tabs through module caching, so other tabs consume IDs too

    • B

      React may render more than once per commit: Strict Mode double-renders, and interrupted renders are discarded

    • C

      JavaScript integers overflow after a few thousand increments

    • D

      Hooks reset module variables between renders

    Show the answer and explanation

    Answer: B

    Render must be pure because React may render a component several times and commit only once: Strict Mode renders twice in development, and concurrent rendering can abandon renders that were interrupted or suspended. Mutating outside variables during render therefore leaks the extra attempts. Use useId for IDs, or move side effects into event handlers or effects.

    Why the other options are wrong

    • A. Each tab has its own JavaScript heap and module instances.

    • C. Numbers stay exact up to 2^53; overflow is not the issue.

    • D. Hooks do not touch module scope.

  5. Question 5State and Hooks

    This hook is used in a Client Component that Next.js pre-renders on the server. Which two problems does it have? (Choose two.)

    function useLocalStorage(key, initial) {
      const [value, setValue] = useState(() => {
        const saved = localStorage.getItem(key);
        return saved !== null ? JSON.parse(saved) : initial;
      });
      // ...
      return [value, setValue];
    }

    Choose 2.

    • A

      The server render throws a ReferenceError, because localStorage does not exist there

    • B

      Guarding it with a typeof window check makes the first client render differ from the server HTML

    • C

      useState cannot accept a function as its initial value

    • D

      localStorage.getItem is asynchronous, so value starts as a Promise

    • E

      The value is shared automatically by every component that uses the same key

    Show the answer and explanation

    Answer: A and B

    Browser-only data must not change what the first client render produces. Two good options: useSyncExternalStore with a getServerSnapshot that returns initial (React then re-renders with the stored value after hydration), or start with initial and read storage in an effect.

    Why the other options are wrong

    • C. Lazy initialisers are supported and only run on the first render.

    • D. localStorage is a synchronous API.

    • E. Each call has its own state; they only sync if you listen for storage events.

  6. Question 6Architecture and Modern React

    In TanStack Query v5, ['products', { page: 1, sort: 'price' }] and ['products', { sort: 'price', page: 1 }] refer to the same cache entry.

    • A

      True

    • B

      False

    Show the answer and explanation

    Answer: A

    Query keys are hashed with a stable serializer that sorts object keys, so { page, sort } and { sort, page } match. Array order still matters: ['products', 1] and [1, 'products'] are different keys. Put every variable the query function depends on into the key.

    Why the other options are wrong

    • B. TanStack Query sorts object keys when it hashes, so both keys produce the same hash.

  7. Question 7Components and Rendering

    In React 19, ReactDOM.render(<App />, container) still works but logs a deprecation warning.

    • A

      True

    • B

      False

    Show the answer and explanation

    Answer: B

    React 18 deprecated the legacy root API, and React 19 removed ReactDOM.render, ReactDOM.hydrate, unmountComponentAtNode and findDOMNode from react-dom. Apps must use createRoot or hydrateRoot from react-dom/client, which also enable concurrent features.

    Why the other options are wrong

    • A. It no longer works in React 19: ReactDOM.render was removed, not just deprecated.

  8. Question 8Performance and Concurrency

    Which two statements about transitions are true? (Choose two.)

    Choose 2.

    • A

      An urgent update (such as typing) can interrupt a transition render that is in progress

    • B

      setState calls inside a setTimeout callback started from within startTransition are not marked as transitions

    • C

      Transitions run the render on a background thread so the main thread stays free

    • D

      Transitions delay network requests until the browser is idle

    • E

      A transition that suspends always shows the nearest Suspense fallback

    Show the answer and explanation

    Answer: A and B

    Transitions mark updates as non-urgent. React renders them in small chunks on the main thread and gives way to urgent updates. Only updates scheduled while the callback is running are marked, so a setTimeout inside startTransition loses the mark unless you call startTransition inside the timer as well.

    Why the other options are wrong

    • C. React renders on the main thread; it yields between units of work instead.

    • D. Transitions affect rendering priority, not when fetches start.

    • E. Already-revealed content stays visible during a transition.

  9. Question 9State and Hooks

    A component loads data with fetch('/api/orders').then(r => r.json()).then(setOrders).catch(showError). When the API returns 404 with an HTML error page, what happens, and how does axios differ?

    • A

      fetch rejects on any non-2xx status, so showError runs, just like axios

    • B

      fetch resolves, so r.json() fails on HTML; axios rejects a 404

    • C

      Both resolve normally and pass the error page to setOrders as a string

    • D

      fetch retries 404s three times automatically before resolving

    Show the answer and explanation

    Answer: B

    The fetch promise rejects only when the request can't be completed, such as a network error or an abort. A 404 or 500 still resolves with res.ok === false. Here r.json() then throws a parse error on the HTML, so the user sees a confusing message rather than "not found". Check if (!res.ok) throw new Error(…). axios rejects for statuses outside 2xx by default (validateStatus), parses JSON for you, and also supports AbortController signals for cancellation.

    Why the other options are wrong

    • A. fetch rejects only on network failures; HTTP errors still resolve.

    • C. Here r.json() throws on HTML; and axios rejects non-2xx responses by default.

    • D. fetch never retries; retries come from libraries or your own code.

  10. Question 10Architecture and Modern React

    A Server Component imports logView from a 'use server' file and calls await logView(slug) during render. What happens?

    • A

      React sends a POST request to its own server to invoke the action, which adds a network hop

    • B

      It runs as an ordinary async function call on the server, with no network request

    • C

      It throws, because Server Actions can only be invoked from forms or Client Components

    • D

      It is deferred until after the response has streamed, like an analytics beacon sent from the page

    Show the answer and explanation

    Answer: B

    'use server' tells the bundler to give client code a reference that POSTs to the server. Server Components already run on the server, so importing and calling the function is a plain async call. For work that shouldn't block the response, such as logging, Next.js provides after().

    Why the other options are wrong

    • A. On the server, a Server Function is just an async function and is called directly.

    • C. They can be called from Server Components too; they just aren't endpoints in that case.

    • D. Awaiting it blocks the render like any other awaited call; deferral needs after() or similar.

Practise all 489 REACT questions

Start with the free 15-question diagnostic. It shows where to focus, and your results carry over if you sign up.

Go to REACT