LearnFrenzy
Sign in Take a free test

Testing and Interview Prep · Lesson 31 of 31

React Interview Questions

8 min read Updated Nov 8, 2026 Saurabh Samir

React interviews test whether you understand how React thinks: rendering, state, effects and data flow. Below are the questions that come up most often in frontend interviews, from fresher level to senior, with short answers and runnable examples where a demo explains it better than words.

In this lesson

  • Fundamentals: virtual DOM, JSX, props vs state, keys
  • Hooks: useState, useEffect, useRef, custom hooks
  • Rendering and performance
  • React 19 and the ecosystem

Fundamentals

1. What is the virtual DOM, and what is reconciliation?

Rendering a component produces a tree of plain JavaScript objects describing the UI. When state changes, React renders again, compares the new tree with the old one (reconciliation, or "diffing") and applies only the differences to the real DOM. It assumes elements of a different type produce different trees, and uses keys to match list items.

2. Props vs state?

PropsState
passed in by the parentowned by the component
read-only inside the componentchanged with its setter
like function argumentslike the component's memory

Both trigger a re-render when they change.

3. Why are keys needed in lists, and why not the index?

Keys let React match items between renders. If the index is the key and an item is removed or reordered, React attaches the old item's state and DOM to the wrong row. Use a stable id from your data. (See the live demo in the lists and keys lesson.)

4. Controlled vs uncontrolled components?

A controlled input's value comes from React state (value + onChange); an uncontrolled input keeps its own value in the DOM (defaultValue, read with a ref or FormData). Controlled gives instant validation and formatting; uncontrolled is simpler when you only need values on submit.

5. What does "lifting state up" mean?

Moving state to the closest common parent of the components that need it, and passing it down as props with callbacks to change it – one source of truth.

Hooks

6. Why does the count only go up by 1?

import { useState } from "react";

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

Result

[Count: 0]

› click “Count: 0”
[Count: 2]

A classic trick question. The answer is 2, not 3 or 1. count is a snapshot (0) for this render, so both setCount(count + 1) calls queue "set to 1". The updater then runs on the queued value: 1 + 1 = 2. Updates are batched into one render.

7. Explain the useEffect dependency array.

No array: runs after every render. []: after the first render only. [a, b]: after the first render and whenever a or b change. Return a cleanup function to undo subscriptions and timers; it runs before the next effect and on unmount.

8. What's wrong with this effect?

import { useEffect, useState } from "react";

export default function App() {
  const [seconds, setSeconds] = useState(0);
  useEffect(() => {
    const id = setInterval(() => setSeconds(seconds + 1), 100);
    return () => clearInterval(id);
  }, []);                                          // seconds is missing – the callback keeps seeing 0
  return <p>Seconds: {seconds}</p>;
}

Result

Seconds: 0

› wait 350ms
Seconds: 1

A stale closure: the interval callback captured seconds = 0 from the first render, so it sets 1 forever. Fix it with the updater form, setSeconds((s) => s + 1), which doesn't need seconds as a dependency.

9. useRef vs useState?

Changing state re-renders the component; changing ref.current doesn't. Use refs for DOM nodes and values the screen doesn't depend on (timer IDs, previous values).

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

Call hooks only at the top level (not in conditions or loops) and only from components or custom hooks. React identifies each hook by its call order; changing the order between renders would mix up their state.

11. What is a custom hook?

A function starting with use that calls other hooks to reuse stateful logic (e.g. useDebounce, useLocalStorage). It shares logic, not state – each caller gets its own.

Rendering and performance

12. When does a component re-render?

When its state changes, its parent re-renders, or a context it uses changes. Props changing is a consequence of the parent re-rendering.

13. memo vs useMemo vs useCallback?

memo skips re-rendering a component when its props are shallowly equal; useMemo caches a computed value; useCallback caches a function so a memoised child or an effect sees the same reference. The React Compiler now adds most of this automatically.

14. What does this render?

export default function App() {
  const items = [];
  const user = { name: "Asha", score: 0 };
  return (
    <div>
      <p>{items.length && "You have items"}</p>
      <p>Score: {user.score || "N/A"}</p>
      <p>{null}{undefined}{false}{true}Done</p>
    </div>
  );
}

Result

0
Score: N/A
Done

A stray 0 (numbers are rendered), "Score: N/A" (because 0 || "N/A" – use ?? to keep 0), and "Done" (null, undefined and booleans render nothing).

15. Why do effects run twice in development?

StrictMode mounts, unmounts and remounts components in development to reveal effects without proper cleanup. It doesn't happen in production.

React 19 and the ecosystem

16. What's new in React 19?

  • Actions: async functions in <form action> and transitions, with useActionState, useFormStatus and useOptimistic.
  • use to read promises (with Suspense) and context, even conditionally.
  • ref as a normal prop (no forwardRef), <Context value> as a provider, ref cleanup functions.
  • Document metadata (<title>, <meta>) rendered from components, and stylesheet and preload support.
  • Server Components and Server Actions, used through frameworks such as Next.js; plus the React Compiler for automatic memoisation.

17. What are Server Components?

Components that run only on the server (or at build time). They can be async, read databases or files directly, and send rendered output to the browser without their JavaScript. Interactive parts are marked "use client". They're used through frameworks like Next.js's App Router.

18. How do you manage global state?

Keep most state local; put server data in TanStack Query (or framework loaders) and filters in the URL. For the remaining shared UI state, use Context (+ useReducer) for rarely changing values, and Zustand or Redux Toolkit for frequently changing, widely used state.

19. How do you prevent XSS in React?

React escapes text in JSX automatically. The risks are dangerouslySetInnerHTML (sanitise with DOMPurify first), javascript: URLs in href built from user input, and server-side injection. Never trust client-side checks for security.

import { useEffect, useState } from "react";

const all = ["React", "Redux", "React Router", "Remix", "Next.js", "Node.js"];
const search = (q) =>
  new Promise((resolve) => setTimeout(() => resolve(all.filter((x) => x.toLowerCase().includes(q.toLowerCase()))), 200));

export default function App() {
  const [query, setQuery] = useState("");
  const [results, setResults] = useState([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    if (!query.trim()) { setResults([]); return; }
    let ignore = false;
    const id = setTimeout(async () => {             // debounce: wait 300 ms after the last key
      setLoading(true);
      const data = await search(query);
      if (!ignore) { setResults(data); setLoading(false); }   // ignore stale responses
    }, 300);
    return () => { ignore = true; clearTimeout(id); };
  }, [query]);

  return (
    <div>
      <input aria-label="Search" value={query} onChange={(e) => setQuery(e.target.value)} />
      {loading ? <p>Searching…</p> : <ul>{results.map((r) => <li key={r}>{r}</li>)}</ul>}
    </div>
  );
}

Result

[]

› type “re” into Search
[re]

› wait 320ms
[re]
Searching…

› wait 250ms
[re]
• React
• Redux
• React Router
• Remix

Interviewers look for: debouncing with cleanup, protection against stale responses, loading and empty states, and keys on the list.

How to answer well

  • Explain the "why": snapshots, re-renders, reconciliation, cleanup.
  • Mention trade-offs (controlled vs uncontrolled, Context vs a store, memoising vs restructuring).
  • In coding rounds, handle loading, error and empty states without being asked.

Keep practising with our React interview question sets and Next.js interview questions.

Practice

Try it yourself

  1. Without running it, predict the console output, then check your answer.

    import { useEffect, useState } from "react";
    
    export default function App() {
      const [n, setN] = useState(0);
      console.log("render", n);
      useEffect(() => {
        console.log("effect", n);
        return () => console.log("cleanup", n);
      }, [n]);
      return <button onClick={() => setN(n + 1)}>Next</button>;
    }
    Show answer

    Console

    render 0
    effect 0
    
    › click “Next”
    render 1
    cleanup 0
    effect 1

    Render happens first, then the effect. On the update, React renders with n = 1, then runs the old effect's cleanup (which still sees 0), then the new effect.

Quick check

What is a stale closure in React?

A function (often in an effect or timer) that captured old props or state from an earlier render.

Why use ?? instead of || for a default?

|| replaces 0 and empty strings too; ?? only replaces null and undefined.

Do Server Components ship their JavaScript to the browser?

No – only their rendered output; client components marked "use client" ship JavaScript.

Summary

  • Know the core model: render, reconcile, commit; props down, events up; state as a snapshot.
  • Be precise about hooks: dependencies, cleanup, updater functions and the rules of hooks.
  • Show awareness of performance, React 19 features and how real apps manage state and data.

Finished this lesson?

Mark it complete to track your progress. You have reached the end of this track — well done!

Search LearnFrenzy

Esc

Quick links