React · Frontend system thinking

How do Suspense and React.lazy work for code splitting?

MediumSuspenseReact.lazycode splittingUpdated Oct 2026
Quiz this track

Short answer

React.lazy loads a component from a dynamic import, and the nearest Suspense boundary shows a fallback while the code loads. Pair it with an error boundary for failed imports.

A dynamic import tells the bundler to put a module in a separate chunk. React.lazy wraps that import so React can treat it as a component that is not ready yet. While the promise is pending, React unwinds to the nearest Suspense boundary and renders its fallback.

jsx
const SettingsPage = React.lazy(() => import("./SettingsPage"));

function App() {
  return (
    <Suspense fallback={<PageSkeleton />}>
      <SettingsPage />
    </Suspense>
  );
}
The SettingsPage chunk is requested only when the lazy component first renders.

Where Suspense helps

  • Route-level splitting so the initial bundle stays small
  • Heavy widgets, editors or charts that are not needed immediately
  • Data that a framework can suspend on, not only component code
  • Keeping a meaningful fallback visible during a slow load

The lazy import should be declared at module scope. Calling lazy inside a component creates a new component type on every render, which can remount the subtree and make the fallback flicker. Prefetch the chunk on hover or navigation intent when the route is likely to be used.

Suspense does not catch rejected imports. A failed chunk request throws, so wrap the lazy subtree in an error boundary and offer a retry or a full page reload.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1Why should React.lazy be called at module scope?
  2. 2How do you handle a failed dynamic import?
  3. 3Does Suspense replace data fetching?
  4. 4How do you prefetch a lazy route?

Say it in the interview

React.lazy turns a dynamic import into a component that React can wait for, and Suspense shows a fallback until the chunk is ready. I use it at route boundaries or for heavy widgets, declare it at module scope, and pair it with an error boundary because a failed import rejects. Suspense can also support framework-level data loading, but by itself it is not a data-fetching solution.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live React mock interview and get scored feedback on depth, clarity and confidence.