Suspense is a React component that lets you show a fallback UI (like a loading spinner) while waiting for something asynchronous to complete — whether that's lazy-loading a component, fetching data, or waiting for server-rendered content.
How it works under the hood:
Use case 1 — Lazy Loading:
1import { lazy, Suspense } from "react";23const Dashboard = lazy(() => import("./Dashboard"));4const Analytics = lazy(() => import("./Analytics"));56function App() {7 return (8 <Suspense fallback={9 <div className="loading-spinner">10 <p>Loading dashboard...</p>11 </div>12 }>13 <Dashboard />14 </Suspense>15 );16}
Use case 2 — Data Fetching with React 19 use():
1import { Suspense, use } from "react";23function UserProfile({ userId }: { userId: string }) {4 // use() suspends the component while the promise is pending5 const user = use(fetchUser(userId));67 return (8 <div>9 <h2>{user.name}</h2>10 <p>{user.email}</p>11 </div>12 );13}1415function App() {16 return (17 <Suspense fallback={<Spinner />}>18 <UserProfile userId="123" />19 </Suspense>20 );21}
Use case 3 — Nested Suspense boundaries: You can place multiple Suspense boundaries to show granular loading states:
1<Suspense fallback={<PageLoader />}>2 <Header /> {/* Loads immediately */}3 <Suspense fallback={<ContentSkeleton />}>4 <MainContent /> {/* Shows skeleton while loading */}5 </Suspense>6 <Suspense fallback={<SidebarSkeleton />}>7 <Sidebar /> {/* Independent loading state */}8 </Suspense>9</Suspense>
Streaming SSR with Suspense: On the server, React can stream HTML to the client. It sends the shell immediately, then streams in Suspense boundaries as they resolve. This means users see content faster — the header appears while the main content is still loading on the server.
Benefits:
Best practices: