React Hooks, State and Performance Interview Questions for MERN Stack
25 React Hooks, State and Performance questions with answers for mern stack roles — 1 easy, 15 medium, 9 hard.
About React Hooks, State and Performance
This topic goes deeper into how real React apps are built and optimised. It covers useEffect, useMemo, useCallback, useRef, useReducer, Context, custom hooks, Redux Toolkit, TanStack Query, code splitting, error boundaries, React 19 features and Server Components. Mid and senior interviews test stale closures, race conditions, re-render problems and state architecture choices.
Sheet progressStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
useRef returns a mutable object whose current property persists across renders without causing a re-render when changed. It is used to access DOM nodes, for example focusing an input or measuring size, and to store values like timer ids, previous values or the latest callback. Do not read or write ref.current during rendering for values that affect output, because React will not re-render when it changes.
02
How does the useEffect dependency array work and why is cleanup important?
useEffect runs after render. With no array it runs after every render, with an empty array only after mount, and with dependencies whenever any of them change by Object.is comparison. The function you return is the cleanup, which runs before the next effect and on unmount. Use it to remove listeners, clear intervals, abort requests and close sockets, otherwise you get leaks and duplicate subscriptions.
03
What is the difference between useMemo and useCallback?
useMemo caches the result of a calculation, recomputing only when dependencies change, for example a filtered and sorted list. useCallback caches a function reference, so useCallback(fn, deps) equals useMemo(() => fn, deps). They help when passing values or callbacks to memoized children or as effect dependencies. They have their own cost, so do not wrap everything; the React Compiler can now add this memoization automatically.
React.memo wraps a component so it skips re-rendering when its props are shallowly equal to the previous props. It helps with expensive components that re-render often because the parent re-renders, such as rows in a large table. It fails if you pass new object, array or function props every render, so pair it with useMemo and useCallback. Measure with React DevTools Profiler before adding it.
05
What is the Context API and when should you avoid it?
Context passes data through the component tree without prop drilling. You create it with createContext, provide a value with a Provider and read it with useContext, or the newer use API. It suits low-frequency global data like theme, language and logged-in user. Avoid it for frequently changing large state, because every consumer re-renders when the value changes; split contexts or use Zustand or Redux Toolkit instead.
06
When should you use useReducer instead of useState?
Use useReducer when state has multiple related fields, when the next state depends on complex logic, or when many event handlers update state in different ways. A reducer is a pure function (state, action) => newState that centralises transitions and is easy to unit test, for example a cart with add, remove, change quantity and clear actions. For simple independent values, useState is clearer.
07
What is a custom hook and what rules must hooks follow?
A custom hook is a function whose name starts with use and that calls other hooks to package reusable stateful logic, such as useFetch, useDebounce or useAuth. Each component using it gets its own state. Hooks must be called at the top level of a component or another hook, never inside conditions, loops or nested functions, so React can match state by call order. The eslint-plugin-react-hooks rules enforce this.
Redux keeps global state in a single store that changes only through dispatched actions handled by reducers. Redux Toolkit is the official modern way to write Redux: configureStore sets up the store with DevTools, createSlice generates actions and reducers and lets you write mutating code safely using Immer, and createAsyncThunk handles async requests. RTK Query adds data fetching and caching. Components use useSelector and useDispatch.
09
How do you implement code splitting in a React app?
Use dynamic import with React.lazy, for example const Admin = lazy(() => import('./Admin')), and wrap it in a Suspense boundary with a fallback. Bundlers like Vite then create a separate chunk that loads only when needed. Split by route first, then by heavy components like charts, editors and maps. Preload likely next routes on hover, and check results with a bundle analyser such as rollup-plugin-visualizer.
10
Props are being passed through five levels of components that do not use them. How would you refactor?
This is prop drilling. First try component composition: pass ready-made elements as children or props so intermediate components do not need the data. If many distant components need it, create a Context with a custom hook like useAuth. For complex or frequently updated shared state, use a store such as Zustand or Redux Toolkit with selectors so only interested components re-render.
11
An error in one dashboard widget crashes the entire React page. How do you contain it?
Wrap risky sections in error boundaries. An error boundary catches rendering errors in its subtree and shows fallback UI instead of unmounting the whole app. React still requires a class with getDerivedStateFromError and componentDidCatch, or you can use the react-error-boundary package. Place boundaries around each widget and the route level, log errors to monitoring, and offer a retry. They do not catch errors in event handlers or async code.
Situation: two freshers joined my team and their PRs had repeated effect bugs. Task: help them ramp up without slowing the sprint. Action: I ran short weekly sessions on effects, keys and state structure, paired with them on real tickets, and wrote a review checklist. I gave specific, kind comments in reviews. Result: within two months their PRs needed far fewer changes, and one of them now runs the sessions.
17
What is the difference between server state and client state, and why use a library like TanStack Query?
Client state is UI data owned by the browser, like modal open or selected tab. Server state lives in the database, can be changed by others, and is only a cached copy in the browser. TanStack Query manages server state with caching, deduplication, background refetching, retries, pagination and mutations with cache invalidation. This removes much hand-written useEffect fetching and stops global stores from holding stale API data.
React 19 added Actions, letting async functions handle form submissions with pending and error state; hooks such as useActionState, useFormStatus and useOptimistic; the use API to read Promises and context; ref as a normal prop instead of forwardRef; support for document metadata tags like title inside components; and stable Server Components. The separate React Compiler can automatically memoize components, reducing manual useMemo and useCallback.
19
Explain CSR, SSR, hydration and React Server Components.
With client-side rendering, the browser downloads JavaScript and builds the page, which is slower for first paint and SEO. Server-side rendering sends ready HTML, then hydration attaches React event handlers in the browser. React Server Components run only on the server, can query data directly, and send no JavaScript for themselves, while client components marked use client handle interactivity. Frameworks like Next.js implement these patterns.
20
Typing in a filter box over a list of 10,000 rows feels laggy. How do you fix it?
First profile to confirm what re-renders. Then virtualise the list with a library like TanStack Virtual or react-window so only visible rows render. Memoise row components and keep the filtered list in useMemo. Use useDeferredValue or startTransition so the input stays responsive while the list update is treated as low priority. For very large data, filter on the server with pagination and an index.
21
A setInterval inside useEffect always logs the initial count value instead of the updated one. Why, and how do you fix it?
This is a stale closure: the effect ran once with an empty dependency array, so its callback captured count from the first render forever. Fixes include using the functional updater setCount((c) => c + 1) so you do not need to read count, adding count to the dependencies with proper cleanup, or storing the latest value in a ref that the interval reads.
22
Your React production bundle is 3 MB and the first load is slow on mobile. What steps do you take?
Analyse the bundle to find the largest modules. Split code by route with React.lazy, lazy load heavy libraries like charts and editors, replace large dependencies with lighter ones, import only needed functions so tree shaking works, and remove unused polyfills. Compress images, serve assets from a CDN with Brotli and long cache headers, and consider SSR or static rendering for landing pages. Track Core Web Vitals after each change.
23
Fast typing in a search box sometimes shows results for an older query. What causes this and how do you fix it?
It is a race condition: responses arrive out of order, so a slow earlier request overwrites results of a newer one. In the effect, use an AbortController and abort the previous request in the cleanup, or keep an ignore flag set to true during cleanup and skip setState when it is set. Debouncing reduces requests, and TanStack Query handles this automatically by keying results to the query.
24
Write a Redux Toolkit slice that fetches products with createAsyncThunk.
Situation: our React app still used Create React App and class components, and builds took several minutes. Task: as the senior developer I proposed moving to Vite and hooks. Action: I wrote a migration plan, moved the build tool first behind a feature branch, fixed environment variable names, then converted components gradually with tests. Result: dev server start went from 40 seconds to 2, builds became much faster, and the team adopted hooks patterns.
Frequently asked questions
How important is React Hooks, State and Performance in MERN Stack interviews?
This topic goes deeper into how real React apps are built and optimised. It covers useEffect, useMemo, useCallback, useRef, useReducer, Context, custom hooks, Redux Toolkit, TanStack Query, code splitting, error boundaries, React 19 features and Server Components. Mid and senior interviews test stale closures, race conditions, re-render problems and state architecture choices.
How should I use the React Hooks, State and Performance sheet?
Go top to bottom — easy to hard. Answer before opening each answer, tick what you solved and save misses to Last-Minute Revision.