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.
- 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
countfrom the render that created it: 0. Every tick sets the state to 1, which React ignores after the first time. Fix it withsetCount(c => c + 1), or with Dan Abramov'suseInterval, 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.
- A
- 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
useContextin 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
useContextcall inReact.cache()so it runs once per request - E
Call
React.createContextinside 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 withuseContext. To share data between Server Components, use props orcache().Why the other options are wrong
C.
'use server'marks Server Functions; it never enables hooks in components.D.
cachememoises 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.
- A
- 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-primarymust 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.btnPrimaryisundefined, and React renders no class at all. Setcss.modules.localsConvention: 'camelCaseOnly'if you prefer camelCase keys. Checked against Vite 8.3, which passeslocalsConventionthrough 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.
- A
- 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.
- A
- 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
localStoragedoes not exist there - B
Guarding it with a
typeof windowcheck makes the first client render differ from the server HTML - C
useStatecannot accept a function as its initial value - D
localStorage.getItemis asynchronous, sovaluestarts 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:
useSyncExternalStorewith agetServerSnapshotthat returnsinitial(React then re-renders with the stored value after hydration), or start withinitialand 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.
- A
- 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.
- A
- 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,unmountComponentAtNodeandfindDOMNodefromreact-dom. Apps must usecreateRootorhydrateRootfromreact-dom/client, which also enable concurrent features.Why the other options are wrong
A. It no longer works in React 19:
ReactDOM.renderwas removed, not just deprecated.
- A
- 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
setStatecalls inside asetTimeoutcallback started from withinstartTransitionare 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.
- A
- 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
fetchrejects on any non-2xx status, soshowErrorruns, just like axios - B
fetchresolves, sor.json()fails on HTML; axios rejects a 404 - C
Both resolve normally and pass the error page to
setOrdersas a string - D
fetchretries 404s three times automatically before resolving
Show the answer and explanation
Answer: B
The
fetchpromise rejects only when the request can't be completed, such as a network error or an abort. A 404 or 500 still resolves withres.ok === false. Herer.json()then throws a parse error on the HTML, so the user sees a confusing message rather than "not found". Checkif (!res.ok) throw new Error(…). axios rejects for statuses outside 2xx by default (validateStatus), parses JSON for you, and also supportsAbortControllersignals for cancellation.Why the other options are wrong
A.
fetchrejects only on network failures; HTTP errors still resolve.C. Here
r.json()throws on HTML; and axios rejects non-2xx responses by default.D.
fetchnever retries; retries come from libraries or your own code.
- A
- Question 10Architecture and Modern React
A Server Component imports
logViewfrom a'use server'file and callsawait 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 providesafter().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.
- A
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.