Parallele Routen
Parallele Routen (Parallel Routes) ermöglichen es Ihnen, eine oder mehrere Seiten gleichzeitig oder bedingt innerhalb desselben Layouts zu rendern. Sie sind nützlich für hochdynamische Bereiche einer Anwendung, wie Dashboards und Feeds in sozialen Netzwerken.
Beispielsweise können Sie bei einem Dashboard parallele Routen verwenden, um die Seiten team
und analytics
gleichzeitig zu rendern:

Konvention
Slots
Parallele Routen werden mit benannten Slots erstellt. Slots werden mit der @folder
-Konvention definiert. Die folgende Dateistruktur definiert beispielsweise zwei Slots: @analytics
und @team
:

Slots werden als Props an das übergeordnete Layout übergeben. Für das obige Beispiel akzeptiert die Komponente in app/layout.js
nun die Slot-Props @analytics
und @team
und kann sie parallel zum children
-Prop rendern:
export default function Layout({
children,
team,
analytics,
}: {
children: React.ReactNode
analytics: React.ReactNode
team: React.ReactNode
}) {
return (
<>
{children}
{team}
{analytics}
</>
)
}
export default function Layout({ children, team, analytics }) {
return (
<>
{children}
{team}
{analytics}
</>
)
}
Slots sind jedoch keine Routensegmente und beeinflussen die URL-Struktur nicht. Für /@analytics/views
lautet die URL beispielsweise /views
, da @analytics
ein Slot ist. Slots werden mit der regulären Page-Komponente kombiniert, um die endgültige Seite zu bilden, die mit dem Routensegment verknüpft ist. Daher können Sie auf derselben Ebene des Routensegments keine separaten statischen und dynamischen Slots haben. Wenn ein Slot dynamisch ist, müssen alle Slots auf dieser Ebene dynamisch sein.
Gut zu wissen:
- Das
children
-Prop ist ein impliziter Slot, der keinem Ordner zugeordnet werden muss. Das bedeutet, dassapp/page.js
äquivalent zuapp/@children/page.js
ist.
default.js
Sie können eine default.js
-Datei definieren, die als Fallback für nicht übereinstimmende Slots während des initialen Ladens oder eines vollständigen Seitenneuaufbaus gerendert wird.
Betrachten Sie die folgende Ordnerstruktur. Der @team
-Slot hat eine /settings
-Seite, aber @analytics
nicht.

Bei der Navigation zu /settings
rendert der @team
-Slot die /settings
-Seite, während die aktuell aktive Seite für den @analytics
-Slot beibehalten wird.
Beim Neuladen rendert Next.js eine default.js
für @analytics
. Wenn default.js
nicht vorhanden ist, wird stattdessen ein 404
-Fehler gerendert.
Da children
ein impliziter Slot ist, müssen Sie auch eine default.js
-Datei erstellen, um ein Fallback für children
zu rendern, wenn Next.js den aktiven Zustand der übergeordneten Seite nicht wiederherstellen kann.
Verhalten
Standardmäßig behält Next.js den aktiven Zustand (oder die Unterseite) für jeden Slot bei. Der Inhalt, der innerhalb eines Slots gerendert wird, hängt jedoch von der Art der Navigation ab:
- Soft Navigation: Bei der clientseitigen Navigation führt Next.js ein partielles Rendering durch, ändert die Unterseite innerhalb des Slots und behält die aktiven Unterseiten der anderen Slots bei, auch wenn sie nicht mit der aktuellen URL übereinstimmen.
- Hard Navigation: Nach einem vollständigen Seitenladen (Browser-Neuladen) kann Next.js den aktiven Zustand für die Slots, die nicht mit der aktuellen URL übereinstimmen, nicht bestimmen. Stattdessen wird eine
default.js
-Datei für die nicht übereinstimmenden Slots gerendert oder404
, wenndefault.js
nicht vorhanden ist.
Gut zu wissen:
- Der
404
-Fehler für nicht übereinstimmende Routen stellt sicher, dass Sie nicht versehentlich eine parallele Route auf einer Seite rendern, für die sie nicht vorgesehen war.
Beispiele
Mit useSelectedLayoutSegment(s)
Sowohl useSelectedLayoutSegment
als auch useSelectedLayoutSegments
akzeptieren einen parallelRoutesKey
-Parameter, mit dem Sie das aktive Routensegment innerhalb eines Slots auslesen können.
'use client'
import { useSelectedLayoutSegment } from 'next/navigation'
export default function Layout({ auth }: { auth: React.ReactNode }) {
const loginSegment = useSelectedLayoutSegment('auth')
// ...
}
'use client'
import { useSelectedLayoutSegment } from 'next/navigation'
export default function Layout({ auth }) {
const loginSegment = useSelectedLayoutSegment('auth')
// ...
}
Wenn ein Benutzer zu app/@auth/login
(oder /login
in der URL-Leiste) navigiert, ist loginSegment
gleich dem String "login"
.
Bedingte Routen
Sie können parallele Routen verwenden, um Routen basierend auf bestimmten Bedingungen, wie der Benutzerrolle, bedingt zu rendern. Beispielsweise, um eine unterschiedliche Dashboard-Seite für die Rollen /admin
oder /user
zu rendern:

import { checkUserRole } from '@/lib/auth'
export default function Layout({
user,
admin,
}: {
user: React.ReactNode
admin: React.ReactNode
}) {
const role = checkUserRole()
return role === 'admin' ? admin : user
}
import { checkUserRole } from '@/lib/auth'
export default function Layout({ user, admin }) {
const role = checkUserRole()
return role === 'admin' ? admin : user
}
Tab-Gruppen
Sie können ein layout
innerhalb eines Slots hinzufügen, um Benutzern zu ermöglichen, den Slot unabhängig zu navigieren. Dies ist nützlich für die Erstellung von Tabs.
Beispielsweise hat der @analytics
-Slot zwei Unterseiten: /page-views
und /visitors
.

Erstellen Sie innerhalb von @analytics
eine layout
-Datei, um die Tabs zwischen den beiden Seiten zu teilen:
import Link from 'next/link'
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<nav>
<Link href="/page-views">Page Views</Link>
<Link href="/visitors">Visitors</Link>
</nav>
<div>{children}</div>
</>
)
}
import Link from 'next/link'
export default function Layout({ children }) {
return (
<>
<nav>
<Link href="/page-views">Page Views</Link>
<Link href="/visitors">Visitors</Link>
</nav>
<div>{children}</div>
</>
)
}
Modale Fenster
Parallele Routen können zusammen mit Intercepting Routes verwendet werden, um modale Fenster mit Deep Linking zu erstellen. Dies ermöglicht es Ihnen, häufige Herausforderungen beim Erstellen von modalen Fenstern zu lösen, wie:
- Teilbarkeit des modalen Inhalts über eine URL.
- Beibehaltung des Kontexts beim Aktualisieren der Seite, anstatt das modale Fenster zu schließen.
- Schließen des modalen Fensters bei Rückwärtsnavigation, anstatt zur vorherigen Route zu gehen.
- Wiederöffnen des modalen Fensters bei Vorwärtsnavigation.
Betrachten Sie das folgende UI-Muster, bei dem ein Benutzer ein Login-Modalfenster aus einem Layout mit clientseitiger Navigation öffnen oder eine separate /login
-Seite aufrufen kann:

Um dieses Muster zu implementieren, erstellen Sie zunächst eine /login
-Route, die Ihre Haupt-Login-Seite rendert.

import { Login } from '@/app/ui/login'
export default function Page() {
return <Login />
}
import { Login } from '@/app/ui/login'
export default function Page() {
return <Login />
}
Fügen Sie dann im @auth
-Slot eine default.js
-Datei hinzu, die null
zurückgibt. Dadurch wird sichergestellt, dass das modale Fenster nicht gerendert wird, wenn es nicht aktiv ist.
export default function Default() {
return null
}
export default function Default() {
return null
}
Interzeptieren Sie im @auth
-Slot die /login
-Route, indem Sie den /(.)login
-Ordner aktualisieren. Importieren Sie die <Modal>
-Komponente und ihre Kinder in die /(.)login/page.tsx
-Datei:
import { Modal } from '@/app/ui/modal'
import { Login } from '@/app/ui/login'
export default function Page() {
return (
<Modal>
<Login />
</Modal>
)
}
import { Modal } from '@/app/ui/modal'
import { Login } from '@/app/ui/login'
export default function Page() {
return (
<Modal>
<Login />
</Modal>
)
}
Gut zu wissen:
- Die verwendete Konvention zum Abfangen der Route, z.B.
(.)
, hängt von Ihrer Dateisystemstruktur ab. Siehe Intercepting Routes convention.- Durch die Trennung der
<Modal>
-Funktionalität vom modalen Inhalt (<Login>
) können Sie sicherstellen, dass jeglicher Inhalt innerhalb des modalen Fensters, z.B. Formulare, Server Components sind. Siehe Interleaving Client and Server Components für weitere Informationen.
Öffnen des modalen Fensters
Nun können Sie den Next.js-Router nutzen, um das modale Fenster zu öffnen und zu schließen. Dies stellt sicher, dass die URL korrekt aktualisiert wird, wenn das modale Fenster geöffnet ist, und bei Vorwärts- und Rückwärtsnavigation.
Um das modale Fenster zu öffnen, übergeben Sie den @auth
-Slot als Prop an das übergeordnete Layout und rendern ihn zusammen mit dem children
-Prop.
import Link from 'next/link'
export default function Layout({
auth,
children,
}: {
auth: React.ReactNode
children: React.ReactNode
}) {
return (
<>
<nav>
<Link href="/login">Open modal</Link>
</nav>
<div>{auth}</div>
<div>{children}</div>
</>
)
}
import Link from 'next/link'
export default function Layout({ auth, children }) {
return (
<>
<nav>
<Link href="/login">Open modal</Link>
</nav>
<div>{auth}</div>
<div>{children}</div>
</>
)
}
Wenn der Benutzer auf den <Link>
klickt, öffnet sich das modale Fenster, anstatt zur /login
-Seite zu navigieren. Bei einem Neuladen oder initialen Laden navigiert der Aufruf von /login
jedoch zur Haupt-Login-Seite.
Schließen des modalen Fensters
Sie können das modale Fenster schließen, indem Sie router.back()
aufrufen oder die Link
-Komponente verwenden.
'use client'
import { useRouter } from 'next/navigation'
export function Modal({ children }: { children: React.ReactNode }) {
const router = useRouter()
return (
<>
<button
onClick={() => {
router.back()
}}
>
Close modal
</button>
<div>{children}</div>
</>
)
}
'use client'
import { useRouter } from 'next/navigation'
export function Modal({ children }) {
const router = useRouter()
return (
<>
<button
onClick={() => {
router.back()
}}
>
Close modal
</button>
<div>{children}</div>
</>
)
}
Wenn Sie die Link
-Komponente verwenden, um von einer Seite wegzunavigieren, die den @auth
-Slot nicht mehr rendern soll, müssen Sie sicherstellen, dass die parallele Route auf eine Komponente verweist, die null
zurückgibt. Zum Beispiel erstellen wir beim Navigieren zurück zur Root-Seite eine @auth/page.tsx
-Komponente:
import Link from 'next/link'
export function Modal({ children }: { children: React.ReactNode }) {
return (
<>
<Link href="/">Close modal</Link>
<div>{children}</div>
</>
)
}
import Link from 'next/link'
export function Modal({ children }) {
return (
<>
<Link href="/">Close modal</Link>
<div>{children}</div>
</>
)
}
export default function Page() {
return null
}
export default function Page() {
return null
}
Oder wenn Sie zu einer anderen Seite navigieren (z.B. /foo
, /foo/bar
, etc.), können Sie einen Catch-all-Slot verwenden:
export default function CatchAll() {
return null
}
export default function CatchAll() {
return null
}
Gut zu wissen:
- Wir verwenden eine Catch-all-Route in unserem
@auth
-Slot, um das modale Fenster zu schließen, aufgrund des Verhaltens von parallelen Routen(#behavior). Da clientseitige Navigationen zu einer Route, die nicht mehr mit dem Slot übereinstimmt, sichtbar bleiben, müssen wir den Slot auf eine Route verweisen, dienull
zurückgibt, um das modale Fenster zu schließen.- Weitere Beispiele könnten das Öffnen eines Foto-Modalfensters in einer Galerie sein, während auch eine dedizierte
/photo/[id]
-Seite vorhanden ist, oder das Öffnen eines Warenkorbs in einem seitlichen modalen Fenster.- Sehen Sie sich ein Beispiel für modale Fenster mit abgefangenen und parallelen Routen an.
Lade- und Fehler-UI
Parallele Routen können unabhängig voneinander gestreamt werden, sodass Sie unabhängige Fehler- und Ladezustände für jede Route definieren können:

Weitere Informationen finden Sie in der Dokumentation zu Loading UI und Error Handling.