Loading & streaming in Next.js

From the Next.js cheat sheet · Data Fetching · verified Jul 2026

Loading & streaming

typescript
// app/products/loading.tsx
export default function Loading() {
  return (
    <div className="animate-pulse">
      <div className="h-8 bg-gray-200 rounded w-1/4 mb-4"></div>
      <div className="grid grid-cols-3 gap-4">
        {[...Array(6)].map((_, i) => (
          <div key={i} className="h-40 bg-gray-200 rounded"></div>
        ))}
      </div>
    </div>
  )
}

// Using Suspense for parts of the page
import { Suspense } from 'react'

export default function ProductPage() {
  return (
    <div>
      <h1>Products</h1>
      
      <Suspense fallback={<div>Loading products...</div>}>
        <ProductList /> {/* Async Server Component */}
      </Suspense>
      
      <Suspense fallback={<div>Loading reviews...</div>}>
        <Reviews /> {/* Another async component */}
      </Suspense>
    </div>
  )
}

// Streaming with generateMetadata
export async function generateMetadata(
  { params }: { params: Promise<{ id: string }> }
) {
  // This runs in parallel with the page
  const { id } = await params
  const product = await getProduct(id)
  
  return {
    title: product.name,
    description: product.description,
  }
}

// Progressive enhancement with loading boundaries
export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <div>
      <nav>Static Navigation</nav>
      
      <Suspense fallback={<SidebarSkeleton />}>
        <Sidebar /> {/* Async component */}
      </Suspense>
      
      <main>
        <Suspense fallback={<ContentSkeleton />}>
          {children}
        </Suspense>
      </main>
    </div>
  )
}
💡 loading.tsx shows while data loads
⚡ Suspense for granular loading states
📌 Streaming allows progressive rendering
🟢 Skeleton UI improves perceived performance

More Next.js tasks

Back to the full Next.js cheat sheet