layout.js
Die layout
-Datei wird verwendet, um ein Layout in Ihrer Next.js-Anwendung zu definieren.
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}
export default function DashboardLayout({ children }) {
return <section>{children}</section>
}
Ein Root Layout ist das oberste Layout im Stammverzeichnis app
. Es wird verwendet, um die <html>
- und <body>
-Tags sowie andere global geteilte UI-Elemente zu definieren.
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
Referenz
Props
children
(erforderlich)
Layout-Komponenten sollten eine children
-Prop akzeptieren und verwenden. Während des Renderings wird children
mit den Routensegmenten gefüllt, die das Layout umschließt. Dies sind in erster Linie die Komponenten eines untergeordneten Layouts (falls vorhanden) oder einer Seite, aber auch andere spezielle Dateien wie Loading oder Error, falls zutreffend.
params
(optional)
Ein Promise, das sich zu einem Objekt auflöst, das die dynamischen Routenparameter vom Root-Segment bis zu diesem Layout enthält.
export default async function Layout({
params,
}: {
params: Promise<{ team: string }>
}) {
const { team } = await params
}
export default async function Layout({ params }) {
const { team } = await params
}
Beispiel-Route | URL | params |
---|---|---|
app/dashboard/[team]/layout.js | /dashboard/1 | Promise<{ team: '1' }> |
app/shop/[tag]/[item]/layout.js | /shop/1/2 | Promise<{ tag: '1', item: '2' }> |
app/blog/[...slug]/layout.js | /blog/1/2 | Promise<{ slug: ['1', '2'] }> |
- Da die
params
-Prop ein Promise ist, müssen Sieasync/await
oder Reactsuse
-Funktion verwenden, um auf die Werte zuzugreifen.- In Version 14 und früher war
params
eine synchrone Prop. Zur Abwärtskompatibilität können Sie in Next.js 15 weiterhin synchron darauf zugreifen, aber dieses Verhalten wird in Zukunft veraltet sein.
- In Version 14 und früher war
Root Layout
Das app
-Verzeichnis muss ein Root-app/layout.js
enthalten.
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html>
<body>{children}</body>
</html>
)
}
export default function RootLayout({ children }) {
return (
<html>
<body>{children}</body>
</html>
)
}
- Das Root-Layout muss
<html>
- und<body>
-Tags definieren.- Sie sollten nicht manuell
<head>
-Tags wie<title>
und<meta>
zu Root-Layouts hinzufügen. Verwenden Sie stattdessen die Metadata API, die erweiterte Anforderungen wie Streaming und Deduplizierung von<head>
-Elementen automatisch handhabt.
- Sie sollten nicht manuell
- Sie können Route Groups verwenden, um mehrere Root-Layouts zu erstellen.
- Die Navigation zwischen mehreren Root-Layouts verursacht einen vollständigen Seitenneuladevorgang (im Gegensatz zu einer clientseitigen Navigation). Beispielsweise verursacht die Navigation von
/cart
, dasapp/(shop)/layout.js
verwendet, zu/blog
, dasapp/(marketing)/layout.js
verwendet, einen vollständigen Seitenneuladevorgang. Dies gilt nur für mehrere Root-Layouts.
- Die Navigation zwischen mehreren Root-Layouts verursacht einen vollständigen Seitenneuladevorgang (im Gegensatz zu einer clientseitigen Navigation). Beispielsweise verursacht die Navigation von
Einschränkungen
Request-Objekt
Layouts werden während der Navigation im Client zwischengespeichert, um unnötige Server-Anfragen zu vermeiden.
Layouts werden nicht neu gerendert. Sie können zwischengespeichert und wiederverwendet werden, um unnötige Berechnungen bei der Navigation zwischen Seiten zu vermeiden. Durch die Beschränkung des Zugriffs auf den rohen Request in Layouts kann Next.js die Ausführung von potenziell langsamen oder teuren Benutzercode im Layout verhindern, was die Leistung negativ beeinflussen könnte.
Um auf das Request-Objekt zuzugreifen, können Sie die headers
- und cookies
-APIs in Server Components und Functions verwenden.
import { cookies } from 'next/headers'
export default async function Layout({ children }) {
const cookieStore = await cookies()
const theme = cookieStore.get('theme')
return '...'
}
import { cookies } from 'next/headers'
export default async function Layout({ children }) {
const cookieStore = await cookies()
const theme = cookieStore.get('theme')
return '...'
}
Query-Parameter
Layouts werden bei der Navigation nicht neu gerendert, daher können sie nicht auf Suchparameter zugreifen, die sonst veraltet wären.
Um auf aktualisierte Query-Parameter zuzugreifen, können Sie die searchParams
-Prop der Seite verwenden oder sie in einer Client-Komponente mit dem useSearchParams
-Hook lesen. Da Client-Komponenten bei der Navigation neu gerendert werden, haben sie Zugriff auf die neuesten Query-Parameter.
'use client'
import { useSearchParams } from 'next/navigation'
export default function Search() {
const searchParams = useSearchParams()
const search = searchParams.get('search')
return '...'
}
'use client'
import { useSearchParams } from 'next/navigation'
export default function Search() {
const searchParams = useSearchParams()
const search = searchParams.get('search')
return '...'
}
import Search from '@/app/ui/search'
export default function Layout({ children }) {
return (
<>
<Search />
{children}
</>
)
}
import Search from '@/app/ui/search'
export default function Layout({ children }) {
return (
<>
<Search />
{children}
</>
)
}
Pfadname
Layouts werden bei der Navigation nicht neu gerendert, daher können sie nicht auf den Pfadnamen zugreifen, der sonst veraltet wäre.
Um auf den aktuellen Pfadnamen zuzugreifen, können Sie ihn in einer Client-Komponente mit dem usePathname
-Hook lesen. Da Client-Komponenten bei der Navigation neu gerendert werden, haben sie Zugriff auf den neuesten Pfadnamen.
import { Breadcrumbs } from '@/app/ui/Breadcrumbs'
export default function Layout({ children }) {
return (
<>
<Breadcrumbs />
<main>{children}</main>
</>
)
}
import { Breadcrumbs } from '@/app/ui/Breadcrumbs'
export default function Layout({ children }) {
return (
<>
<Breadcrumbs />
<main>{children}</main>
</>
)
}
Datenabruf
Layouts können keine Daten an ihre children
übergeben. Sie können jedoch dieselben Daten in einer Route mehrmals abrufen und Reacts cache
verwenden, um die Anfragen ohne Leistungseinbußen zu deduplizieren.
Alternativ werden Anfragen bei Verwendung von fetch
in Next.js automatisch dedupliziert.
export async function getUser(id: string) {
const res = await fetch(`https://.../users/${id}`)
return res.json()
}
import { getUser } from '@/app/lib/data'
import { UserName } from '@/app/ui/user-name'
export default async function Layout({ children }) {
const user = await getUser('1')
return (
<>
<nav>
{/* ... */}
<UserName user={user.name} />
</nav>
{children}
</>
)
}
import { getUser } from '@/app/lib/data'
import { UserName } from '@/app/ui/user-name'
export default async function Layout({ children }) {
const user = await getUser('1')
return (
<>
<nav>
{/* ... */}
<UserName user={user.name} />
</nav>
{children}
</>
)
}
import { getUser } from '@/app/lib/data'
import { UserName } from '@/app/ui/user-name'
export default async function Page() {
const user = await getUser('1')
return (
<div>
<h1>Welcome {user.name}</h1>
</div>
)
}
import { getUser } from '@/app/lib/data'
import { UserName } from '@/app/ui/user-name'
export default async function Page() {
const user = await getUser('1')
return (
<div>
<h1>Welcome {user.name}</h1>
</div>
)
}
Zugriff auf untergeordnete Segmente
Layouts haben keinen Zugriff auf die Routensegmente unterhalb ihrer selbst. Um auf alle Routensegmente zuzugreifen, können Sie useSelectedLayoutSegment
oder useSelectedLayoutSegments
in einer Client-Komponente verwenden.
import { NavLink } from './nav-link'
import getPosts from './get-posts'
export default async function Layout({
children,
}: {
children: React.ReactNode
}) {
const featuredPosts = await getPosts()
return (
<div>
{featuredPosts.map((post) => (
<div key={post.id}>
<NavLink slug={post.slug}>{post.title}</NavLink>
</div>
))}
<div>{children}</div>
</div>
)
}
import { NavLink } from './nav-link'
import getPosts from './get-posts'
export default async function Layout({ children }) {
const featuredPosts = await getPosts()
return (
<div>
{featuredPosts.map((post) => (
<div key={post.id}>
<NavLink slug={post.slug}>{post.title}</NavLink>
</div>
))}
<div>{children}</div>
</div>
)
}
Beispiele
Metadaten
Sie können die <head>
-HTML-Elemente wie title
und meta
mit dem metadata
-Objekt oder der generateMetadata
-Funktion ändern.
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Next.js',
}
export default function Layout({ children }: { children: React.ReactNode }) {
return '...'
}
export const metadata = {
title: 'Next.js',
}
export default function Layout({ children }) {
return '...'
}
Gut zu wissen: Sie sollten nicht manuell
<head>
-Tags wie<title>
und<meta>
zu Root-Layouts hinzufügen. Verwenden Sie stattdessen die Metadata APIs, die erweiterte Anforderungen wie Streaming und Deduplizierung von<head>
-Elementen automatisch handhaben.
Aktive Navigationslinks
Sie können den usePathname
-Hook verwenden, um festzustellen, ob ein Navigationslink aktiv ist.
Da usePathname
ein Client-Hook ist, müssen Sie die Navigationslinks in eine Client-Komponente auslagern, die in Ihr Layout importiert werden kann:
import { NavLinks } from '@/app/ui/nav-links'
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<NavLinks />
<main>{children}</main>
</body>
</html>
)
}
import { NavLinks } from '@/app/ui/nav-links'
export default function Layout({ children }) {
return (
<html lang="en">
<body>
<NavLinks />
<main>{children}</main>
</body>
</html>
)
}
Anzeigen von Inhalten basierend auf params
Mithilfe von dynamischen Routensegmenten können Sie spezifische Inhalte anzeigen oder abrufen, die auf der params
-Prop basieren.
export default async function DashboardLayout({
children,
params,
}: {
children: React.ReactNode
params: Promise<{ team: string }>
}) {
const { team } = await params
return (
<section>
<header>
<h1>Willkommen im Dashboard von {team}</h1>
</header>
<main>{children}</main>
</section>
)
}
export default async function DashboardLayout({ children, params }) {
const { team } = await params
return (
<section>
<header>
<h1>Willkommen im Dashboard von {team}</h1>
</header>
<main>{children}</main>
</section>
)
}
Lesen von params
in Client Components
Um params
in einer Client Component (die nicht async
sein kann) zu verwenden, können Sie die use
-Funktion von React nutzen, um das Promise zu lesen:
'use client'
import { use } from 'react'
export default function Page({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = use(params)
}
'use client'
import { use } from 'react'
export default function Page({ params }) {
const { slug } = use(params)
}
Versionsverlauf
Version | Änderungen |
---|---|
v15.0.0-RC | params ist jetzt ein Promise. Ein Codemod ist verfügbar. |
v13.0.0 | layout eingeführt. |