Skip to content
tezvyn:

How do React.lazy and dynamic import() enable code splitting?

Source: react.devMediumHow cards are made

How do React.lazy and dynamic import() enable code splitting?

It tests your grasp of React code-splitting and the Suspense contract. A strong answer states that lazy defers loading until first render via dynamic import, and Suspense shows a fallback while the Promise resolves.

What's really being asked

This question probes whether you understand React's declarative code-splitting API at a mechanical level rather than just surface syntax. The interviewer wants to see if you can articulate the exact contract between a lazy loader function, the Promise returned by dynamic import, the module shape, and a Suspense boundary. Senior candidates should demonstrate awareness of caching semantics, the default export requirement, and the distinction between network suspense and local UI state management.

The full answer

A strong response hits four mechanical points in order. First, lazy is a factory that accepts a loader function which must return a Promise or thenable from a dynamic import call. Second, React invokes that loader only when the component is first rendered, then caches both the Promise and its resolved value so the load never repeats across re-renders or remounts. Third, the resolved module must expose its React component as the default export, and that component type must be valid such as a function, memo, or forwardRef. Fourth, Suspense acts as a boundary that catches the thrown Promise during rendering and displays a fallback element until the Promise resolves, at which point React commits the resolved component in place of the fallback.

The mistakes people make

Red flags include saying Suspense is exclusively for data fetching or server components, claiming that lazy preloads the chunk before mount, or suggesting you can consume named exports directly without re-exporting them as default. Another mistake is describing the fallback as a prop on lazy rather than on the parent Suspense boundary, or implying that the loader runs during module initialization instead of deferred first render. Confusing the Promise rejection path with a render error is also a signal that the candidate has not handled production lazy loading.

What usually comes next

An interviewer might ask how you would handle a rejected Promise, which should be caught by an Error Boundary rather than Suspense. They may also ask how to prefetch a lazy route on hover, how server-side rendering streams interact with lazy and Suspense, or whether you can nest multiple Suspense boundaries for granular fallbacks inside a single view. You might also be asked to compare React.lazy with framework-level splitting such as Next.js dynamic.

A concrete example

Imagine a settings page with a heavy Chart component. You write const Chart = lazy(() => import('./Chart.js')); and render Chart inside a Suspense boundary with fallback Spinner. When the user clicks the Analytics tab, React calls the loader, triggers the network request for the split chunk, and shows Spinner. Once the chunk arrives and the modules default export resolves to a valid component, React swaps Spinner for Chart. If the network request fails, the thrown rejection propagates to the nearest Error Boundary, which can render an error state.

Interview question

Which statement accurately describes the runtime behavior when a React.lazy component is first rendered within a Suspense boundary?

  • a.Suspense catches any rejected Promise from the import and renders an error UI instead of the fallback.
  • b.The loader runs during module initialization to preload the chunk, so Suspense never shows a fallback on first render.
  • c.React invokes the loader on first render, caches the result, and Suspense displays a fallback until the Promise resolves.Correct
  • d.The lazy component can be a named export from the dynamically imported module without any re-exporting.
Why?

React calls the lazy loader only on first render and caches both the Promise and resolved module, while Suspense catches the thrown Promise to show a fallback. Distractor A is wrong because lazy does not preload during module initialization; loading is deferred until the component is first rendered.

Just read this? Test yourself on what you have been reading.

Read the original → react.dev

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you 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

We are hiring for this. Open roles that interview on react — each one lists the topics its interview covers.

See open roles