CPCODELAB
React

Suspense and React.lazy — Code Splitting

11 min read

Loading Components on Demand

React.lazy lets you defer loading a component until it is first rendered. Combined with <Suspense>, you can show a fallback (spinner, skeleton) while the bundle chunk downloads. This reduces initial bundle size and speeds up page load.

jsx
import { lazy, Suspense } from "react";

// The import() call is what triggers code-splitting
const HeavyDashboard = lazy(() => import("./HeavyDashboard"));
const AnalyticsChart = lazy(() => import("./AnalyticsChart"));

function App() {
  return (
    <Suspense fallback={<p>Loading dashboard...</p>}>
      <HeavyDashboard />
    </Suspense>
  );
}

Nested Suspense boundaries

You can nest multiple <Suspense> boundaries to show granular loading states. Each boundary catches the nearest suspended subtree independently — outer boundaries don't need to wait for inner ones.

jsx
function Dashboard() {
  return (
    <div className="dashboard">
      <Suspense fallback={<Skeleton type="header" />}>
        <DashboardHeader />
      </Suspense>
      <Suspense fallback={<Skeleton type="chart" />}>
        <AnalyticsChart />
      </Suspense>
      <Suspense fallback={<Skeleton type="table" />}>
        <RecentActivity />
      </Suspense>
    </div>
  );
}

In React 18+, <Suspense> also integrates with data fetching via frameworks like Next.js App Router. Server Components and use(promise) can suspend while data loads, giving you the same fallback UX for async data as for lazy components.

Ready to test yourself?
Practice React— quiz & coding exercises