Suspense enables declarative loading states for async data.
Code:
1import { Suspense, use } from "react";23// Resource that suspends4const userPromise = fetchUser(1).then(res => res.json());56function UserProfile() {7 const user = use(userPromise); // Suspends here8 return (9 <div>10 <h1>{user.name}</h1>11 <p>{user.email}</p>12 </div>13 );14}1516function App() {17 return (18 <div>19 <Header />20 <Suspense fallback={<div>Loading profile...</div>}>21 <UserProfile />22 </Suspense>23 <Footer />24 </div>25 );26}
How it works:
use(userPromise)Nested Suspense:
1<Suspense fallback={<PageSkeleton />}>2 <Header />3 <Suspense fallback={<ContentSkeleton />}>4 <MainContent />5 </Suspense>6 <Suspense fallback={<SidebarSkeleton />}>7 <Sidebar />8 </Suspense>9</Suspense>
With TanStack Query:
1import { Suspense } from "react";2import { useQuery } from "@tanstack/react-query";34function UserProfile({ userId }) {5 const { data: user } = useQuery({6 queryKey: ["user", userId],7 queryFn: () => fetchUser(userId),8 suspense: true, // Enables Suspense9 });1011 return <div>{user.name}</div>;12}1314<Suspense fallback={<Spinner />}>15 <UserProfile userId={1} />16</Suspense>
Benefits: