typescriptintermediate
Next.js Streaming with Suspense
Stream server components with Suspense boundaries for progressive page loading and better TTFB.
typescriptPress ⌘/Ctrl + Shift + C to copy
// app/dashboard/page.tsx
import { Suspense } from 'react';
export default function Dashboard() {
return (
<div className="space-y-4">
<h1>Dashboard</h1>
{/* Fast content renders immediately */}
<WelcomeCard />
{/* Slow content streams in with loading fallback */}
<Suspense fallback={<AnalyticsSkeleton />}>
<Analytics />
</Suspense>
<Suspense fallback={<RecentOrdersSkeleton />}>
<RecentOrders />
</Suspense>
</div>
);
}
function WelcomeCard() {
return <div className="p-4 bg-blue-50 rounded-lg">Welcome back!</div>;
}
// Slow async server component — streams when ready
async function Analytics() {
const res = await fetch('https://api.example.com/analytics', {
cache: 'no-store',
});
const data = await res.json();
return (
<div className="grid grid-cols-3 gap-4">
<StatCard label="Users" value={data.users} />
<StatCard label="Revenue" value={`$${data.revenue}`} />
<StatCard label="Orders" value={data.orders} />
</div>
);
}
async function RecentOrders() {
const res = await fetch('https://api.example.com/orders?limit=5');
const orders = await res.json();
return (
<ul>
{orders.map((o: { id: string; amount: number }) => (
<li key={o.id}>Order #{o.id} — ${o.amount}</li>
))}
</ul>
);
}
function AnalyticsSkeleton() {
return <div className="h-24 bg-gray-200 animate-pulse rounded-lg" />;
}
function RecentOrdersSkeleton() {
return <div className="h-40 bg-gray-200 animate-pulse rounded-lg" />;
}
function StatCard({ label, value }: { label: string; value: string | number }) {
return (
<div className="p-4 bg-white rounded-lg shadow">
<p className="text-sm text-gray-500">{label}</p>
<p className="text-2xl font-bold">{value}</p>
</div>
);
}Use Cases
- Progressive loading for data-heavy dashboards
- Improving perceived performance with streaming
- Independent loading states for page sections
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptadvanced
Partial Prerendering with Suspense
Combine static shells with streamed dynamic content using React Suspense for instant page loads.
Best for: E-commerce product pages
#ppr#suspense
typescriptintermediate
Streaming with Loading UI and Suspense
Use loading.tsx and React Suspense to stream UI progressively in Next.js App Router.
Best for: dashboards
#nextjs#streaming
typescriptbeginner
Next.js Image Optimization Patterns
Advanced next/image usage with responsive sizes, blur placeholders, and custom loaders.
Best for: Optimizing Core Web Vitals with proper image loading
#nextjs#image
typescriptadvanced
Caching Strategies in Next.js
Master Next.js caching with fetch cache, unstable_cache, revalidatePath, and revalidateTag patterns.
Best for: ISR page caching
#nextjs#caching