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