DEV Community

Cover image for 🚀 Why Next.js Needs Parallel & Intercepting Routes (and React Router Doesn’t) — The Missing Mental Model
Vishwark
Vishwark

Posted on

🚀 Why Next.js Needs Parallel & Intercepting Routes (and React Router Doesn’t) — The Missing Mental Model

Modern routing is no longer about just switching pages.
We expect real-app behavior:

  • Open a detail view in a modal
  • Keep the list in the background
  • Preserve scroll position
  • Go back with browser’s back button
  • Direct URL loads the full page (SEO-friendly)
  • Open modals from anywhere in the app

If you're coming from React Router, this is easy.
But when you try to do the same in Next.js App Router, things suddenly feel… complicated.

Why does Next.js need Parallel Routes and Intercepting Routes, while React Router just uses <Outlet />?

Let’s get to the core reason — and once you see it, everything else makes sense.


🎯 The Real Reason: File-Based Routing Has Limitations That Component-Based Routers Don’t

React Router is powered by a declarative routing tree:
You explicitly write parent → child → nested child routes.

<Route path="posts" element={<PostsPage />}>
  <Route path=":id" element={<PostModal />} />
</Route>
Enter fullscreen mode Exit fullscreen mode

This means:

  • Navigating to /posts/:id naturally renders both parent + child.
  • Parent stay mounted.
  • Child can be rendered as modal.
  • Scroll position in parent is preserved.
  • Nested flows are automatic.

💡 Modals, sidebars, and split views feel “free” in React Router.
They come directly from the route tree.


❌ But Next.js Doesn’t Have a Declarative Route Tree

Instead, it has file-based routing.

app/posts/page.tsx          → /posts
app/posts/[id]/page.tsx     → /posts/:id
Enter fullscreen mode Exit fullscreen mode

These two files are siblings — not parent and child.
Meaning:

❌ Navigating to /posts/10 DOES NOT render /posts/page.tsx.

❌ Your list page does NOT stay in the background.

❌ You can't overlay a modal by default.

❌ You can’t preserve scroll or state automatically.

❌ No <Outlet /> equivalent inside page files.

This is the root of all the pain.

Next.js needed new primitives because its core routing rules do not naturally support nested UI behavior.

So the framework added:

⭐ Parallel Routes

⭐ Intercepting Routes

Two powerful features that patch the gap created by file-based routing.

Let’s break down why.


🟦 1. Why Parallel Routes Are Needed

Parallel routes allow multiple route segments to render at the same time.

React Router can do this because:

  • The parent route stays mounted
  • The child route can appear inside it

In Next.js file routing:

  • /posts and /posts/[id] do not mount together
  • The router replaces the whole screen
  • Background UI is destroyed

So Next.js needed a way to keep multiple routes alive.

Parallel routes add multiple slots:

children → main content
@modal   → modal content
@sidebar → sidebar content
Enter fullscreen mode Exit fullscreen mode

This gives you:

  • Persistent background routes
  • Preserved state + scroll
  • Multiple independent layouts
  • Multiple simultaneous route branches (previously impossible in file routing)

🔥 This is something <Outlet/> gives React Router for free, but Next.js must explicitly implement.


🟥 2. Why Intercepting Routes Are Needed

Parallel routes alone don’t solve the other big challenge:

“How do we decide whether /posts/10 should show a modal or a full-page?”

React Router solves this naturally:

  • Route context is inherited
  • Child routes render within parent
  • Direct URL loads child alone = full page
  • Navigation from parent renders child in Outlet = modal style

Next.js has no nested route relationships between files, so it cannot infer this.

Intercepting routes tell Next.js:

  • When user navigates from within /posts → show modal version
  • When user opens /posts/10 directly → show full-page version

This behavior is impossible in pure file-based routing without explicit routing rules.

Intercepting routes override the route lookup to show different UI depending on navigation context — just like Instagram, Twitter, YouTube modals.


🧩 Final Mental Model

⭐ React Router

Component-based routing

  • Nested routes → natural parent/child rendering
  • Modals, keeps background alive → automatic
  • One routing tree handles everything

⭐ Next.js

File-based routing

  • Sibling pages don’t share parent/child behavior
  • No nested UI by default
  • Background page disappears on navigation
  • Needs additional routing primitives

So Next.js introduces:

Feature Purpose
Parallel Routes Render multiple routes together (background + modal)
Intercepting Routes Choose modal vs full-page based on user navigation

Together, they recreate the nested UI abilities React Router already has — but in a file-based routing architecture.


🔥 TL;DR (Copy This to Remember)

❌ File-based routing can’t express nested route behavior

/posts isn’t the parent of /posts/:id

❌ Background UI disappears on navigation

❌ No automatic modal-in-parent layouts

✔ Parallel Routes = multiple active route branches

✔ Intercepting Routes = context-based route rendering

⭐ These features exist BECAUSE file-based routing cannot do what React Router does naturally.


Top comments (0)