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>
}

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>
  )
}

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 hauptsächlich die Komponente eines untergeordneten Layouts (falls vorhanden) oder einer Seite, aber es können auch andere spezielle Dateien wie Loading oder Error sein, wenn 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
}
Beispiel-RouteURLparams
app/dashboard/[team]/layout.js/dashboard/1Promise<{ team: '1' }>
app/shop/[tag]/[item]/layout.js/shop/1/2Promise<{ tag: '1', item: '2' }>
app/blog/[...slug]/layout.js/blog/1/2Promise<{ slug: ['1', '2'] }>
  • Da die params-Prop ein Promise ist, müssen Sie async/await oder Reacts use-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.

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>
  )
}
  • 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 können Route-Gruppen verwenden, um mehrere Root-Layouts zu erstellen.
    • Die Navigation zwischen mehreren Root-Layouts verursacht einen vollständigen Seitenladevorgang (im Gegensatz zu einer clientseitigen Navigation). Beispielsweise verursacht die Navigation von /cart, das app/(shop)/layout.js verwendet, zu /blog, das app/(marketing)/layout.js verwendet, einen vollständigen Seitenladevorgang. Dies gilt nur für mehrere Root-Layouts.

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 das rohe Request-Objekt kann Next.js die Ausführung von potenziell langsamen oder teurem Benutzercode innerhalb des Layouts verhindern, was die Leistung beeinträchtigen könnte.

Um auf das Request-Objekt zuzugreifen, können Sie die headers- und cookies-APIs in Server-Komponenten und Funktionen verwenden.

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 auslesen. 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 '...'
}

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 auslesen. Da Client-Komponenten bei der Navigation neu gerendert werden, haben sie Zugriff auf den neuesten Pfadnamen.

'use client'

import { usePathname } from 'next/navigation'

// Vereinfachte Breadcrumb-Logik
export default function Breadcrumbs() {
  const pathname = usePathname()
  const segments = pathname.split('/')

  return (
    <nav>
      {segments.map((segment, index) => (
        <span key={index}>
          {' > '}
          {segment}
        </span>
      ))}
    </nav>
  )
}

Datenabfrage

Layouts können keine Daten an ihre children weitergeben. Sie können jedoch dieselben Daten in einer Route mehrmals abfragen und Reacts cache verwenden, um die Anfragen zu deduplizieren, ohne die Leistung zu beeinträchtigen.

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()
}

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.

'use client'

import Link from 'next/link'
import { useSelectedLayoutSegment } from 'next/navigation'

export default function NavLink({
  slug,
  children,
}: {
  slug: string
  children: React.ReactNode
}) {
  const segment = useSelectedLayoutSegment()
  const isActive = slug === segment

  return (
    <Link
      href={`/blog/${slug}`}
      // Ändern Sie den Stil, je nachdem, ob der Link aktiv ist
      style={{ fontWeight: isActive ? 'bold' : 'normal' }}
    >
      {children}
    </Link>
  )
}

Beispiele

Metadaten

Sie können die <head>-HTML-Elemente wie title und meta mit dem metadata-Objekt oder der generateMetadata-Funktion anpassen.

import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'Next.js',
}

export default function Layout({ children }: { children: React.ReactNode }) {
  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.

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:

'use client'

import { usePathname } from 'next/navigation'
import Link from 'next/link'

export function NavLinks() {
  const pathname = usePathname()

  return (
    <nav>
      <Link className={`link ${pathname === '/' ? 'active' : ''}`} href="/">
        Startseite
      </Link>

      <Link
        className={`link ${pathname === '/about' ? 'active' : ''}`}
        href="/about"
      >
        Über uns
      </Link>
    </nav>
  )
}

Inhalte basierend auf params anzeigen

Mithilfe von dynamischen Routensegmenten können Sie spezifische Inhalte basierend auf der params-Prop anzeigen oder abrufen.

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>
  )
}

params in Client Components lesen

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)
}

Versionsverlauf

VersionÄnderungen
v15.0.0-RCparams ist jetzt ein Promise. Ein Codemod ist verfügbar.
v13.0.0layout eingeführt.