Skip to main content
The loading.js file creates an automatic React Suspense boundary around the page.js file and its children. The fallback UI is shown immediately on navigation and swapped for the real content once it finishes streaming.
app/dashboard/loading.js

Parameters

Loading UI components do not accept any parameters.

Behavior

Instant loading states

The fallback UI is prefetched along with the route, so navigation feels instant. You can use any lightweight UI: skeletons, spinners, or a partial preview of the page content (cover photo, title, etc.). loading.js automatically wraps page.js and nested layouts in a <Suspense> boundary within the same route segment.
  • Navigation is interruptible — users can navigate away before the page finishes loading
  • Shared layouts remain interactive while new segments load
  • The fallback is prefetched, making navigation feel immediate

Layouts and loading.js

loading.js sits below layout.js in the component hierarchy. This means it cannot show a fallback for uncached or runtime data access in the layout itself (such as cookies(), headers(), or uncached fetch calls). To ensure instant navigation when a layout fetches data:
  • Wrap runtime data access in the layout with its own <Suspense> boundary
  • Move uncached data fetching from layout.js into page.js
app/dashboard/layout.js

Status codes

Streamed responses return a 200 status code. Errors and not-found states are communicated through the streamed content itself. Because headers are sent before streaming begins, the status code cannot be changed after streaming starts.

Platform support

Examples

Skeleton loading UI

app/dashboard/loading.js

Granular Suspense boundaries

You can also manually place <Suspense> boundaries for individual components rather than wrapping the entire page:
app/dashboard/page.js
This gives you:
  1. Streaming server rendering — HTML is progressively sent from server to client
  2. Selective hydration — React prioritizes making the most-interacted components interactive first

Pending state with useFormStatus

For <Form> submissions, use useFormStatus to show pending state before the loading UI appears:
app/ui/search-button.js

Version history