mediumReact#49

Suspense with React.lazy

Prompt

Lazy-load a heavy component using React.lazy and Suspense. Show "Loading..." fallback while it loads.

Solution

const HeavyComponent = React.lazy(() => import('./HeavyComponent'))

export default function App() {
  return (
    <Suspense fallback={<Text>Loading...</Text>}>
      <HeavyComponent />
    </Suspense>
  )
}
Mentor's take

React.lazy is code splitting expressed in the component model. The user-facing problem: without splitting, your bundle grows with every feature and everyone pays the download cost of screens they may never open. import('./HeavyComponent') is a dynamic import the bundler turns into a separate chunk, fetched over the network only when the component first renders.

Mechanics: lazy wraps the import promise in a component. On first render it suspends — signalling "I'm not ready" — and the nearest <Suspense> boundary above it catches that and shows fallback until the chunk resolves; then the real component renders in place. This is the same suspension mechanism React 18+ uses for data fetching, which is why the boundary is a generic Suspense, not something lazy-specific. Constraints worth naming: lazy requires a default export (wrap named exports: .then(m => ({ default: m.Named }))), call it at module scope — inside a component it creates a new lazy component each render and refetches — and boundary placement is design: one per route gives page-level loading; nested boundaries let the shell render while a widget streams in.

A network fetch can fail, so a production lazy component pairs Suspense with an error boundary for the chunk-load failure case.

Red flag: Lazy-loading everything. Splitting has a cost — a network round-trip at interaction time. Split at route boundaries and for genuinely heavy, rarely-used components; the login screen should not lazy-load its button.

Say it: "lazy turns a dynamic import into a component that suspends; Suspense catches the suspension and shows the fallback — I split at route boundaries and pair it with an error boundary for failed chunks."