Loading states
This page explains how to implement loading states for route segments in Next.js using the loading.tsx
special file.
Creating a loading state
To implement a loading state, create a loading.tsx
file in any route segment where you want loading UI to appear. Next.js automatically wraps the route’s content in a React Suspense boundary.
Directoryapp
Directoryproducts
- loading.tsx
- page.tsx
export default function ProductListLoading() { return <h1>Loading products...</h1>;}
The loading component displays while the page content loads, then gets replaced once content is ready.
Nested loading states
Loading states can be nested within route segments. Each loading.tsx file creates a Suspense boundary for its segment:
export default function ProductLoading() { return <h1>Loading products...</h1>;}
Streaming with Suspense
For more granular control, use Suspense directly in your components:
import { Suspense } from "react";import Loading from "./loading";
export default function ProductPage() { return ( <div> <h1>Product Details</h1>
<Suspense fallback={<Loading />}> <ProductInfo /> </Suspense>
<Suspense fallback={<Loading />}> <ProductReviews /> </Suspense> </div> );}
Customizing the loading UI
While the examples above show basic text as loading UI, you can enhance the user experience with:
- Skeleton loaders
- Spinners
- Content previews (like image or title placeholders)
Benefits of loading UI
-
Instant feedback: Users receive immediate visual feedback during navigation, making the application feel responsive.
-
Interactive layouts: Shared layouts remain interactive while new content loads — users can continue to use navigation menus and sidebars during content loading.
Example with artificial delay
The loading state might not be visible on fast-loading pages. Here’s an example that adds an artificial delay to demonstrate the loading behavior:
export default async function Products() { await new Promise((resolve) => { setTimeout(() => { resolve(); }, 2000); }); return <h1>Products page</h1>;}
With this delay, the loading UI becomes visible for 2 seconds before the products content appears.
Good to know
- Loading UI appears instantly on navigation
- Layouts remain interactive during loading
- Loading states can be nested for granular feedback
- Works automatically with React Suspense
- Useful for both SSR and client-side transitions