Skip to content
tezvyn:

Top 30 Advanced React & Next.js Interview Questions and Answers

30 advanced multiple-choice React & Next.js interview questions, the deep end: internals, failure modes, and the design calls a senior engineer is expected to defend. They come from 30 bites in the React & Next.js library, the hardest slice of the 144 React & Next.js interview questions in the library. Answer them here or read straight down. Every question carries the correct option, why it is correct, and a link to the bite it came from.

React, Next.js, Remix, RSC, React ecosystem

30 questions. Pick an answer, or open “Show the answer” to read it.

Answers are graded in your browser. Nothing is saved, and no XP or streak is earned here. The app keeps score.

  1. Question 1 of 30

    Which call reflects how Babel transforms the JSX <a href='/home' className='link'>Go Home</a> into React.createElement()?

    Show the answer

    Answer: b · React.createElement('a', {href: '/home', className: 'link'}, 'Go Home')

    The JSX transform emits a quoted string for lowercase host tags, places attributes in the second argument preserving className, and passes text children as the third argument, not inside props. Option A is tempting because the resulting element object has props.children, but the createElement API signature requires children as a separate argument from props.

    Read the full bite: Write the React.createElement() equivalent for this JSX

  2. Question 2 of 30

    Why can using array indices as keys cause state pollution when a list is reordered?

    Show the answer

    Answer: d · React relies on keys to identify elements across renders; indices make React match DOM nodes to the wrong data, preserving state for the wrong item.

    Keys provide sibling-scoped identity, not just a performance shortcut; when indices are reused after reordering, React incorrectly associates the old DOM node and its state with new data. Option A is wrong because keys fundamentally determine state preservation, so unstable keys create correctness bugs rather than merely slower reconciliation.

    Read the full bite: How does React use keys in reconciliation? When do keys cause bugs?

  3. Question 3 of 30

    What is the key architectural difference between passing a render function prop and passing a component reference prop in React?

    Show the answer

    Answer: a · A render function is called by the child with internal data, letting the parent control what renders while the child controls when and where.

    This captures inversion of control: the parent supplies the function (what to render) and the child invokes it with internal data (when and where). Option D is tempting because both patterns enable reuse, but HOCs wrap components at definition time while render props compose at runtime.

    Read the full bite: Can you pass a React component as a prop? Explain Render Props.

  4. Question 4 of 30

    You must measure a rendered DOM element and immediately adjust a modal to prevent visual flicker. Which choice is correct?

    Show the answer

    Answer: d · useLayoutEffect, because it runs synchronously after DOM mutations but before paint, letting you correct layout before it is visible

    useLayoutEffect runs synchronously after React commits DOM changes but before the browser paints, so layout corrections happen before the user sees anything. Option C is tempting because it names the right hook but incorrectly claims it runs after paint, which would actually cause the flicker you are trying to prevent.

    Read the full bite: When would you choose useLayoutEffect over useEffect?

  5. Question 5 of 30

    How should you refactor an effect that needs the latest prop value inside a polling interval without listing that prop as a dependency?

    Show the answer

    Answer: b · Lift the prop value into a ref and read the ref inside the interval with an empty dependency array.

    Lifting the prop into a ref lets the interval read the latest value without re-subscribing, because refs are mutable and do not trigger re-renders. Disabling the rule and reading the prop directly hides the stale closure from the linter and leaves the code vulnerable to refactor hazards.

    Read the full bite: Why is exhaustive-deps critical and when can you disable it?

  6. Question 6 of 30

    In a context-reducer feature, a component only dispatches actions but never reads state. How do you prevent it from re-rendering when state changes?

    Show the answer

    Answer: c · Provide state and dispatch through two separate contexts and consume only the dispatch context

    Splitting state and dispatch into two contexts lets components subscribe only to the stable dispatch function, isolating them from state reference changes. React.memo cannot prevent re-renders caused by a changing context value, and useReducer already returns a stable dispatch, so memoizing it with useCallback does not solve the subscription problem.

    Read the full bite: Describe combining useContext and useReducer for scalable feature state

  7. Question 7 of 30

    When a React Server Component fetches data required by deeply nested Client Components, which pattern correctly respects the server-client boundary?

    Show the answer

    Answer: b · Pass the fetched data as serializable props to the Client Components or to a Client wrapper that distributes them

    Server Components must communicate with Client Components through serializable props because props are the only channel across the RSC boundary. Creating Context in a Server Component is incorrect because Context cannot be created in a Server Component and consumed by a Client Component.

    Read the full bite: Pass server-fetched data from Server Components to nested Client Components

  8. Question 8 of 30

    In a useEffect with setInterval reading a state variable, which fix removes the stale closure without leaking or duplicating timers?

    Show the answer

    Answer: b · Add the state variable to the dependency array and return a cleanup that clears the interval

    Adding the state to the dependency array and returning a cleanup that clears the interval recreates the callback with the latest value and prevents leaks. The functional updater distractor is wrong because functional updates only help inside setState, not inside intervals or event listeners where the closure remains stale.

    Read the full bite: What is a stale closure in React hooks?

  9. Question 9 of 30

    Why does runtime CSS-in-JS specifically degrade interactivity during SSR hydration in Next.js?

    Show the answer

    Answer: b · It runs style serialization and injection on the main thread, competing with hydration

    Runtime style generation executes JavaScript during render, occupying the main thread that hydration needs. It does not block the HTML request, disable concurrency, or refetch CSS over the network.

    Read the full bite: Runtime CSS-in-JS performance pitfalls in SSR Next.js

  10. Question 10 of 30

    When updating a global theme in React, why does mutating a CSS custom property avoid subtree re-renders compared to updating a Context theme object?

    Show the answer

    Answer: a · CSS custom properties are mutated outside React's state, so only the browser recomputes styles without reconciliation.

    CSS custom properties live outside React state, so mutating them via setProperty updates the stylesheet without triggering subtree reconciliation. The most tempting distractor claims variables work inside media query expressions, but var() is only valid in property values, not selectors or query expressions.

    Read the full bite: CSS Custom Properties vs JS Theme Object in React

  11. Question 11 of 30

    When using router.push with shallow: true on the same page in the Next.js Pages Router, which of the following occurs?

    Show the answer

    Answer: c · The URL changes and browser history updates, but getServerSideProps and getStaticProps do not re-run; the page component still re-renders.

    Shallow routing updates the URL and history without re-running getServerSideProps or getStaticProps, but it does not prevent the React page component from re-rendering. Option A is a common misconception because shallow routing only skips server data method execution, not React's render cycle.

    Read the full bite: Explain Shallow Routing in Next.js Pages Router

  12. Question 12 of 30

    In a standard client-side React Router setup versus a Next.js App Router application, what is the critical difference in HTTP semantics when a user visits an unmatched URL?

    Show the answer

    Answer: d · Next.js App Router renders not-found.js on the server and sends a true HTTP 404 status, whereas React Router's catch-all renders in the browser and typically preserves the server's original HTTP 200 response.

    Next.js App Router's not-found.js convention server-renders a true HTTP 404 response, while React Router's wildcard route only manipulates the DOM client-side and leaves the initial document's HTTP 200 status unchanged. Option A is tempting because it reflects the common misconception that a React Router catch-all route affects the HTTP status code, but the framework has no built-in server-side semantics for doing so.

    Read the full bite: How do you handle 404s in React Router and Next.js App Router?

  13. Question 13 of 30

    A 50-field React form drops frames because top-level state updates reconcile all fields on every keystroke. Which strategy best addresses the root architectural cause?

    Show the answer

    Answer: c · Extract fields into isolated components with localized state, applying useMemo only to expensive derived calculations

    Extracting fields into isolated components with localized state ensures only the edited field re-renders, fixing the root architectural cause. Wrapping JSX nodes in useMemo inside the parent render violates Hook rules and does not prevent React from reconciling all children when top-level state changes.

    Read the full bite: Optimize a large form with frequent state updates

  14. Question 14 of 30

    Which pattern best prevents data loss and supports accurate per-step validation when users move non-linearly through a React wizard?

    Show the answer

    Answer: c · Maintain a single root form instance, validate only the current step's Zod slice before advancing, and hydrate defaultValues from localStorage on mount.

    A single root form with per-step Zod slices ensures only touched fields are validated before navigation, while localStorage hydration prevents data loss on refresh. Option A is tempting because it correctly centralizes the form, but validating the entire schema prematurely surfaces errors for untouched future fields and skipping persistence leaves users vulnerable to data loss.

    Read the full bite: Design a multi-step wizard form pattern in React

  15. Question 15 of 30

    Which approach correctly optimizes a large mapped list by keeping a single stable onClick reference while still identifying the clicked item?

    Show the answer

    Answer: a · Define one handler outside the map and read the item id from event.currentTarget.dataset.id

    Defining one handler outside the map and reading the id from event.currentTarget.dataset.id creates exactly one stable function reference regardless of list size. Wrapping items with useCallback inside the map violates the rules of hooks and still allocates N functions, while React.memo alone cannot prevent inline arrows from being recreated each render.

    Read the full bite: How would you avoid new functions per list item without useCallback?

  16. Question 16 of 30

    A dashboard renders 20,000 live-updating rows. Wrapping each row in React.memo improves render performance, but memory and scroll jank remain problematic. Why?

    Show the answer

    Answer: d · Memoization avoids re-renders but leaves every row in the DOM, forcing the browser to retain and layout thousands of off-screen nodes.

    React.memo only skips reconciling unchanged rows but keeps every node in the DOM, so memory and layout costs grow with list size. Distractor D confuses virtualization with lazy loading or pagination—virtualization assumes all data is already available and merely avoids mounting off-screen items.

    Read the full bite: Explain list virtualization and when it beats React.memo

  17. Question 17 of 30

    In Next.js pages router SSR with Redux, what is required to prevent React from discarding server markup during hydration?

    Show the answer

    Answer: b · The server serializes state to an escaped script tag and the client hydrates the store before ReactDOM.hydrate

    The client must bootstrap the Redux store from the server-injected payload before calling ReactDOM.hydrate so the initial render matches the server HTML exactly; initializing during render or refetching afterwards forces React to rebuild the DOM.

    Read the full bite: What is state hydration in Next.js SSR with Redux or Zustand?

  18. Question 18 of 30

    In the proposed Next.js test pyramid, why are integration tests allocated to data fetching and route boundaries instead of expanding end-to-end coverage?

    Show the answer

    Answer: b · They validate framework wiring like middleware redirects without the speed and compute cost of a real browser

    Integration tests target Next.js boundaries to catch framework wiring bugs without the cost of a real browser, while unit tests still dominate for speed. Option C is tempting but wrong because Server Components can be unit tested in a Node.js sandbox, so integration tests should not replace the pyramid base.

    Read the full bite: How do you balance unit, integration, and end-to-end tests in Next.js?

  19. Question 19 of 30

    When testing dozens of protected routes in Cypress, which approach best minimizes setup time while maintaining proper test isolation?

    Show the answer

    Answer: a · Use cy.session to cache validated authentication state and restore it across tests

    cy.session caches the authenticated browser state and restores it instantly across tests while still validating it once, eliminating repeated setup overhead. While cy.request is programmatically correct, running it in every beforeEach still repeats authentication instead of caching it, making it slower than cy.session at scale.

    Read the full bite: Cypress auth strategies: UI login vs programmatic session

  20. Question 20 of 30

    What is the key architectural benefit of using MSW instead of directly mocking axios or fetch in Jest tests?

    Show the answer

    Answer: a · MSW sits below the HTTP client layer, enabling the same network handlers to work across fetch, axios, and other libraries without changing test code

    MSW intercepts requests at the network boundary, so tests exercise real request paths and remain agnostic to the HTTP client library. The idea that MSW is a Jest utility is a common misconception; it is actually a standalone mocking layer that works in both browser and Node environments.

    Read the full bite: MSW vs mocking fetch or axios directly in Jest tests

  21. Question 21 of 30

    Why does a sidebar accordion in app/dashboard/layout.js keep its open state when navigating between /dashboard/settings and /dashboard/profile?

    Show the answer

    Answer: c · Because the dashboard layout acts as a persistent shell that remains mounted during child segment changes

    The dashboard layout stays mounted as a persistent shell when only its child page segment changes, so standard React state survives naturally. The distractor about a dedicated Next.js state management API is wrong because persistence is simply standard React behavior, not a framework-specific API.

    Read the full bite: How do nested layouts work in the App Router?

  22. Question 22 of 30

    When a user hard-refreshes a photo modal opened via an intercepting route inside a @modal parallel slot, which outcome does a robust implementation produce?

    Show the answer

    Answer: b · The full photo page renders because the intercept is bypassed and the slot falls back to its own page.js or default.js.

    A hard refresh bypasses the intercept, so the parallel slot renders the full photo page via its own page.js or default.js. Distractor D misapplies the concrete example where default.js returns null for an inactive slot, not for a bypassed intercept.

    Read the full bite: What are Parallel and Intercepting Routes? Describe a photo gallery modal scenario.

  23. Question 23 of 30

    When architecting a Next.js App Router product page, which approach best aligns with the recommended hybrid data strategy?

    Show the answer

    Answer: a · Fetch review summaries in a Server Component and handle inventory checks with a client fetching library

    Review summaries are stable and SEO-critical, so they belong in a Server Component, whereas inventory checks need optimistic updates and background refetching best handled by a client library. Option C misapplies server deduplication to interactive data that requires instant mutation feedback.

    Read the full bite: Server Component fetch vs. client-side SWR or React Query

  24. Question 24 of 30

    During streaming SSR in the Next.js App Router, what does loading.js do when a Server Component suspends on a slow data fetch?

    Show the answer

    Answer: d · It automatically wraps the route segment in a Suspense boundary so the server streams the shell first.

    loading.js is a framework convention that automatically wraps the route segment in a Suspense fallback, enabling the server to stream the shell instantly while deferring slow data. Option B is a common misconception because loading.js is not a client-side spinner driven by useState or useEffect; it is part of the server streaming architecture.

    Read the full bite: Explain streaming with Server Components, Suspense, and loading.js

  25. Question 25 of 30

    For on-demand ISR triggered by a CMS webhook in Next.js App Router, which implementation is architecturally correct?

    Show the answer

    Answer: d · Create a POST Route Handler that validates a webhook secret, calls revalidatePath, and returns; the next request triggers background regeneration while briefly serving stale content.

    A Route Handler is the proper place to receive webhooks because it can securely validate secrets and mutate shared cache state outside of React's render cycle. Calling revalidatePath inside a Server Component body is illegal because Server Components must remain pure and idempotent during render.

    Read the full bite: How do you implement on-demand revalidation from a CMS webhook?

  26. Question 26 of 30

    In a Next.js App Router dynamic route using generateStaticParams for known slugs, what determines whether an unmatched slug is server-rendered on demand instead of returning a 404?

    Show the answer

    Answer: d · The dynamicParams export set to true or false

    The dynamicParams route segment config controls whether slugs not returned by generateStaticParams are server-rendered on demand or return a 404. Returning fallback true is a Pages Router getStaticPaths pattern that does not apply to App Router, where generateStaticParams has no fallback property.

    Read the full bite: How would you use generateStaticParams for known products and on-demand unknowns?

  27. Question 27 of 30

    When using Next.js Middleware to protect /api/admin/* routes in the Edge Runtime, which approach correctly authenticates the request?

    Show the answer

    Answer: d · Extract the secure session cookie from the request headers, verify the JWT using an Edge-compatible library, and return 401 if invalid.

    Middleware runs in the Edge Runtime without React context, so useSession is unavailable, and the client session object is only for presentation. Heavy database queries like Prisma calls are also unsuitable for the edge because middleware should remain fast and stateless.

    Read the full bite: How would you use Next.js Middleware to protect /api/admin/* routes?

  28. Question 28 of 30

    In a Next.js App Router Route Handler, which approach correctly streams a large text response using the standard Web Streams API without buffering the entire payload?

    Show the answer

    Answer: b · Create a ReadableStream with a controller, encode string chunks via TextEncoder into Uint8Array, enqueue them, and return the stream in a new Response

    The correct approach uses the Web Streams API ReadableStream with TextEncoder to send Uint8Array chunks in a standard Response, which is the App Router pattern. Using res.write relies on the Node.js response object from Pages Router and does not apply to Route Handlers, which expect a Web Response.

    Read the full bite: How do you implement response streaming in a Next.js Route Handler?

  29. Question 29 of 30

    Which pattern correctly implements an httpOnly session cookie flow across requests in the Next.js App Router?

    Show the answer

    Answer: d · Set the cookie in a Route Handler using NextResponse.cookies.set with httpOnly and Secure, then read it in a Server Component using cookies from next/headers

    NextResponse.cookies.set correctly issues an httpOnly cookie from a Route Handler, and cookies from next/headers reads it server-side on the next request. Option A is wrong because browsers block JavaScript from reading httpOnly values through fetch response headers.

    Read the full bite: How to securely set and read httpOnly cookies in Route Handlers

  30. Question 30 of 30

    You pass cache: 'no-store' to a fetch in a Next.js App Router page, but the page still returns stale data. Which cache layer is responsible?

    Show the answer

    Answer: c · The Full Route Cache is still serving the statically generated page

    Passing cache: 'no-store' to fetch disables the Data Cache, yet the page can still be served from the Full Route Cache if the segment remains statically generated. This is a common misconception: fetch-level options do not automatically make a static route dynamic without segment config like export const dynamic = 'force-dynamic'.

    Read the full bite: How do you opt out of static rendering for real-time data?

Could you explain these out loud?

That is what an interview actually tests. Tezvyn gives you questions like these with what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon