nextjs - 💡(How to fix) Fix Documentation misleading: loading.tsx does NOT cascade to child routes [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#89019Fetched 2026-04-08 02:03:31
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Author
Timeline (top)
closed ×1commented ×1labeled ×1locked ×1

The loading.js documentation contains a misleading statement that contradicts the actual behavior of Next.js:

"In the same folder, loading.js will be nested inside layout.js. It will automatically wrap the page.js file and any children below in a <Suspense> boundary."

This statement is incorrect or at minimum very misleading. In practice, loading.tsx does NOT cascade to child routes - it only wraps the page.tsx in the same folder.

Root Cause

The loading.js documentation contains a misleading statement that contradicts the actual behavior of Next.js:

"In the same folder, loading.js will be nested inside layout.js. It will automatically wrap the page.js file and any children below in a <Suspense> boundary."

This statement is incorrect or at minimum very misleading. In practice, loading.tsx does NOT cascade to child routes - it only wraps the page.tsx in the same folder.

Code Example

app/
└── [locale]/
    └── (routes)/
        ├── layout.tsx
        ├── loading.tsxParent loading
        ├── (home)/
        │   └── page.tsxChild with async delay
        └── about/
            └── page.tsxChild with async delay

---

export default async function Home() {
  await new Promise((resolve) => setTimeout(resolve, 3000));
  return <main>Home Content</main>;
}

---

export default async function About() {
  // Any async operation
  return <main>About Content</main>;
}

---

export default function Loading() {
  return <p>Loading...</p>;
}

---

app/[locale]/(routes)/(home)/loading.tsxWorks for (home)/page.tsx
app/[locale]/(routes)/about/loading.tsxWorks for about/page.tsx
RAW_BUFFERClick to expand / collapse

Description

The loading.js documentation contains a misleading statement that contradicts the actual behavior of Next.js:

"In the same folder, loading.js will be nested inside layout.js. It will automatically wrap the page.js file and any children below in a <Suspense> boundary."

This statement is incorrect or at minimum very misleading. In practice, loading.tsx does NOT cascade to child routes - it only wraps the page.tsx in the same folder.

To Reproduce

File structure:

app/
└── [locale]/
    └── (routes)/
        ├── layout.tsx
        ├── loading.tsx       ← Parent loading
        ├── (home)/
        │   └── page.tsx      ← Child with async delay
        └── about/
            └── page.tsx      ← Child with async delay

Code:

app/[locale]/(routes)/(home)/page.tsx:

export default async function Home() {
  await new Promise((resolve) => setTimeout(resolve, 3000));
  return <main>Home Content</main>;
}

app/[locale]/(routes)/about/page.tsx:

export default async function About() {
  // Any async operation
  return <main>About Content</main>;
}

app/[locale]/(routes)/loading.tsx:

export default function Loading() {
  return <p>Loading...</p>;
}

Current Behavior

The loading UI from (routes)/loading.tsx is NOT shown when navigating to:

  • /home (inside route group (home))
  • /about (regular folder)

The page appears blank/frozen during the async operation.

Expected Behavior (Based on Documentation)

According to the phrase "and any children below", the loading.tsx at the (routes) level should wrap ALL child pages in a Suspense boundary, including:

  • Pages in nested route groups like (home)/
  • Pages in regular nested folders like about/

Actual Behavior

The loading UI only appears when loading.tsx is placed in the same folder as the page.tsx:

app/[locale]/(routes)/(home)/loading.tsx  ← Works for (home)/page.tsx
app/[locale]/(routes)/about/loading.tsx   ← Works for about/page.tsx

Impact

This issue affects:

  1. Route groups (name)/ - loading.tsx doesn't cascade through route group boundaries
  2. Regular nested folders about/ - loading.tsx doesn't cascade to any child folders
  3. All developers relying on the documentation to understand loading.tsx behavior

Additional Context

This has been a known issue since Next.js 13 was released:

  • #45021 - "Loading.js not working on nested segment" (closed without documentation fix)
  • #43209 - Parent loading.tsx flashes before nested loading.tsx
  • #62115 - Flash of parent loading in parallel routes

The documentation needs to either:

  1. Clarify that "children below" only means the immediate page.tsx in the same folder, OR
  2. Update Next.js behavior to make loading.tsx actually cascade to all child routes as documented

The phrase "and any children below" strongly implies inheritance/cascading behavior (similar to how layouts work), but this is not the actual behavior.

Suggested Documentation Fix

Change from:

"It will automatically wrap the page.js file and any children below in a <Suspense> boundary."

To:

"It will automatically wrap the page.js file in the same folder in a <Suspense> boundary. Note: loading.tsx does NOT cascade to nested routes - each nested route requires its own loading.tsx file."

Or add a clear warning:

⚠️ Important: Unlike layouts, loading.tsx files do NOT cascade to child routes. You must place a loading.tsx file in each route segment folder that needs loading UI.

Environment

Related Issues

  • #45021 (closed) - Same issue but was closed without documentation update
  • #43209 (closed) - Parent loading flashing issue
  • #62115 (closed) - Parallel routes loading flash

extent analysis

TL;DR

To fix the issue with loading.js not cascading to child routes in Next.js, update the documentation to clarify that loading.js only wraps the page.js file in the same folder, or add a loading.js file to each nested route segment.

Guidance

  • Update the loading.js documentation to reflect the actual behavior, specifying that it only wraps the page.js file in the same folder.
  • Add a loading.js file to each nested route segment that requires a loading UI.
  • Consider adding a clear warning to the documentation to avoid confusion about the cascading behavior of loading.js files.
  • Review related issues (#45021, #43209, #62115) for additional context on the problem.

Example

// app/[locale]/(routes)/loading.tsx (does not cascade to child routes)
export default function Loading() {
  return <p>Loading...</p>;
}

// app/[locale]/(routes)/(home)/loading.tsx (required for child route)
export default function HomeLoading() {
  return <p>Loading Home...</p>;
}

Notes

The current documentation implies that loading.js cascades to child routes, but this is not the actual behavior. Updating the documentation or adding loading.js files to each nested route segment can resolve the issue.

Recommendation

Apply a workaround by adding a loading.js file to each nested route segment, as the current behavior of loading.js is not expected to change. This approach ensures that each route segment has a loading UI without relying on the cascading behavior.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

nextjs - 💡(How to fix) Fix Documentation misleading: loading.tsx does NOT cascade to child routes [1 comments, 2 participants]