Streaming UI
Suspense boundaries, loading states, streaming HTML, and progressive rendering.
Overview
Streaming enables progressive HTML delivery for faster perceived performance.
Key Concepts
- Suspense Boundaries — Wrap async components
- Loading UI —
loading.jsfiles for route loading states - Streaming HTML — Send HTML chunks as they're ready
- Selective Hydration — Hydrate interactive parts first
- Server Components — Stream server-rendered content
Code Examples
// app/dashboard/loading.js
export default function Loading() {
return (
<div className="animate-pulse">
<div className="h-8 bg-gray-200 rounded w-1/3 mb-4" />
<div className="h-4 bg-gray-200 rounded w-2/3 mb-2" />
<div className="h-4 bg-gray-200 rounded w-1/2" />
</div>
);
}
// app/dashboard/page.js
import { Suspense } from 'react';
export default function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<StatsSkeleton />}>
<Stats />
</Suspense>
<div className="grid grid-cols-2 gap-4">
<Suspense fallback={<ChartSkeleton />}>
<AnalyticsChart />
</Suspense>
<Suspense fallback={<TableSkeleton />}>
<RecentOrders />
</Suspense>
</div>
</div>
);
}
async function Stats() {
const stats = await fetchStats();
return (
<div className="grid grid-cols-4 gap-4">
<StatCard title="Revenue" value={stats.revenue} />
<StatCard title="Orders" value={stats.orders} />
<StatCard title="Users" value={stats.users} />
<StatCard title="Conversion" value={stats.conversion} />
</div>
);
}
Practice
Build a dashboard with streaming UI and multiple Suspense boundaries.