Suspense lets you declaratively specify loading states for parts of your component tree.
The Problem Suspense Solves
Traditional approach - imperative loading states:
jsxfunction Profile() { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); // You manage loading state manually if (loading) return <Spinner />; return <ProfileContent user={user} />; }
With Suspense - declarative loading states:
jsxfunction App() { return ( <Suspense fallback={<Spinner />}> <Profile /> </Suspense> ); } function Profile() { const user = use(fetchUser()); // Suspends while loading return <ProfileContent user={user} />; }
How Suspense Works
- Component "suspends" (throws a promise)
- React catches it and shows the fallback
- When promise resolves, React re-renders
- Component receives the data
Basic Usage
jsximport { Suspense } from 'react'; function App() { return ( <div> <h1>My App</h1> <Suspense fallback={<div>Loading profile...</div>}> <ProfileDetails /> </Suspense> </div> ); }
Nested Suspense Boundaries
jsxfunction App() { return ( <Suspense fallback={<PageSkeleton />}> <Header /> <Suspense fallback={<MainSkeleton />}> <MainContent /> </Suspense> <Suspense fallback={<SidebarSkeleton />}> <Sidebar /> </Suspense> </Suspense> ); }
Each Suspense boundary can show its own fallback independently.
Coordinating Multiple Components
Wrap related components in one boundary to reveal together:
jsxfunction ArtistPage({ artist }) { return ( <> <h1>{artist.name}</h1> <Suspense fallback={<Loading />}> {/* Both load together */} <Biography artistId={artist.id} /> <Albums artistId={artist.id} /> </Suspense> </> ); }
š Learn more: Suspense Reference