Topic 34 of 47
loading.js
Overview
Next.js integrates directly with React Suspense. By adding a `loading.tsx` file inside a folder, Next.js automatically wraps the route's `page.tsx` and nested layouts in a Suspense boundary, displaying the loading UI while server components fetch data.
Syntax
tsx
app/
├── layout.tsx
├── loading.tsx <-- Loading UI for the root
└── page.tsx
// app/loading.tsx
export default function Loading() {
// You can add any UI inside Loading, including a Skeleton.
return <div className="spinner">Loading...</div>;
}Common Pitfalls
- `loading.tsx` only applies to server-side data fetching latency or async components. It does not display for client-side data fetching via `useEffect`.
- Since `loading.tsx` is an instant replacement, ensure your loading skeleton matches the dimensions of your final content to prevent Layout Shift.
Real-World Example
How Next.js replaces the loading UI with the actual page:
example
tsx
// Under the hood, Next.js structures your tree like this:
<Layout>
<Suspense fallback={<Loading />}>
{/* Page content streams in here when data is ready */}
<Page />
</Suspense>
</Layout>
// Because Layout is OUTSIDE the Suspense boundary,
// the navigation happens instantly and the Layout (e.g., Navbar/Sidebar)
// remains interactive while the Page content loads.