Intermediate React Interview Questions
12 React interview questions for developers with some experience (2 to 5 years): useMemo, StrictMode effects, context re-renders, React.memo, useReducer, error boundaries and keys. Each answer explains why the other options are wrong.
CoversContextCustom hooksEffectsError handlingHooksKeysMemoPerformanceReactRefsRenderingSsrStateStrict mode
By Deepak KumarPublished Answers checked by Deepak
Take it as a timed test
- 12 questions
- 15 min
- Pass mark 60%
- Answers shown at the end
No sign-up. Your answers and scores stay in this browser.
This intermediate paper has 12 React questions for developers with some experience with roughly 2 to 5 years of experience. It covers useMemo, StrictMode effects, context re-renders, React.memo, useReducer, error boundaries and keys. Ten questions are on this page with full explanations; the timed test also includes two questions that aren't shown here, so practise for understanding rather than memory.
How should you use this paper?
Answer each practice question before opening its explanation, and say your reasoning out loud the way you would in an interview. Then take the timed test: 15 minutes, a pass mark of 60%, with answers shown at the end. Your report breaks your score down by topic and difficulty, and you can retry only the questions you missed.
Practice questions with answers
Try each one before opening the answer. The explanation covers why the other options are wrong. The timed test also uses 2 questions that aren't shown here, so practise for understanding, not memory.
When does wrapping a value in useMemo actually help?
Show answer and explanation
Answer: A. When the calculation is expensive, or when a memoised child needs the same object reference between renders
useMemo skips recomputing until its dependencies change. That pays off for expensive work, such as filtering thousands of items, or to keep an object or array reference stable so a React.memo child or an effect dependency doesn't see a "new" value each render. For cheap values it only adds overhead and noise; measure first. The React Compiler can add this automatically.
In development, your data-fetching effect runs twice when the page loads. Why?
Show answer and explanation
Answer: A. React StrictMode mounts, unmounts and remounts components once to check that effects clean up properly
StrictMode does this only in development, to expose effects that don't clean up: a subscription that isn't removed, or a fetch whose stale result overwrites newer state. The fix is a proper cleanup, such as aborting the request with an AbortController or ignoring the result after cleanup, not turning StrictMode off. In production the effect runs once.
Every consumer of a context re-renders whenever the provider's parent renders, even if the data hasn't changed. What is the usual cause?
Show answer and explanation
Answer: A. The provider gets a new object each render, like value={{ user, setUser }}, so consumers see a changed value
Consumers re-render when the provider's value changes by reference. An object literal written inline is a new object on every render, so every consumer updates. Memoise it with useMemo(() => ({ user, setUser }), [user]), or split rarely-changing and often-changing values into separate contexts.
A child wrapped in React.memo still re-renders on every parent render. The parent passes style={{ margin: 8 }}. Why?
Show answer and explanation
Answer: A. The inline object is new each render, so the shallow prop comparison sees a change
React.memo skips a render only when every prop is equal by Object.is. Inline objects, arrays and arrow functions are recreated on every render, so they never compare equal. Hoist constants outside the component, or use useMemo and useCallback for values that depend on props or state. The React Compiler handles many of these cases for you.
A custom hook's name must start with use, so React and its lint rules know the rules of hooks apply to it.
TrueFalse
Show answer and explanation
Answer: True
True. The use prefix tells React's linter to check that the function only calls hooks at the top level and is only called from components or other hooks. A custom hook is just a function that calls other hooks; each component that uses it gets its own independent state. If a helper calls no hooks, don't prefix it with use.
When is useReducer a better choice than several useState calls?
Show answer and explanation
Answer: A. When many state values change together, or the next state depends on the previous one in several different ways
A reducer puts all the update logic in one pure function: (state, action) => newState. That suits forms, multi-step flows and state where one event updates several fields. It's easy to test without React, and passing dispatch down is simpler than many setters. For one or two independent values, plain useState stays clearer.
Which errors does a React error boundary catch? Select all that apply.
Show answer and explanation
Answer: A. An error thrown while rendering a child + D. An error thrown in a child's lifecycle method or constructor
Error boundaries catch errors during rendering, in lifecycle methods and in constructors of the components below them, and show a fallback UI instead of a blank page. They don't catch errors in event handlers, timers, promises or the boundary itself. Use try/catch in handlers, and store the error in state if you want a boundary to display it.
This button is clicked 3 times. What does it show?
const ref = useRef(0);
return (
<button onClick={() => { ref.current++; console.log(ref.current); }}>
{ref.current}
</button>
);Show answer and explanation
Answer: A. 0, while the console logs 1, 2 and 3
Changing ref.current doesn't trigger a re-render, so the button keeps showing what was rendered last: 0. The value really changes (the console shows 1, 2, 3), but the screen only updates when state or props change. That's the point of refs: values that persist without causing renders, such as timer IDs. Reading refs during render is discouraged for exactly this reason.
How can you reset a form component's internal state when the selected user changes?
Show answer and explanation
Answer: A. Render it with key={userId}: a new key makes React unmount the old instance and mount a fresh one
React keeps a component's state as long as it stays at the same place in the tree with the same type and key. Changing the key tells React it's a different component, so the old one unmounts and a new one starts with fresh state. That's cleaner than syncing state from props in an effect, which renders twice and is easy to get wrong.
Match each rendering strategy to how the HTML is produced.
- CSR
- SSR
- SSG
- ISR
- Pre-built pages are regenerated in the background after a set time or on demand
- HTML is generated once at build time
- The server renders HTML on each request
- The browser builds the page with JavaScript after loading a mostly empty HTML file
Show answer and explanation
Answer: CSR → The browser builds the page with JavaScript after loading a mostly empty HTML fileSSR → The server renders HTML on each requestSSG → HTML is generated once at build timeISR → Pre-built pages are regenerated in the background after a set time or on demand
Client-side rendering is simple to host but slower to show content and weaker for SEO. SSR sends ready HTML per request, which is good for personalised or fast-changing pages. Static generation is the fastest to serve. Incremental static regeneration, as in Next.js, keeps static speed while refreshing pages without a full rebuild. Many apps mix all four per route.
Answered them all? Take the same questions against the clock and get a topic-by-topic report.
Start the timed test