layout.js

Le fichier layout est utilisé pour définir une mise en page dans votre application Next.js.

export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return <section>{children}</section>
}

Une mise en page racine (root layout) est la mise en page la plus haute dans le répertoire racine app. Elle est utilisée pour définir les balises <html> et <body> ainsi que d'autres éléments d'interface utilisateur partagés globalement.

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

Référence

Props

children (requis)

Les composants de mise en page doivent accepter et utiliser une prop children. Pendant le rendu, children sera rempli avec les segments de route que la mise en page englobe. Il s'agira principalement du composant d'un Layout enfant (s'il existe) ou d'une Page, mais pourrait également être d'autres fichiers spéciaux comme Loading ou Error le cas échéant.

params (optionnel)

Une promesse qui se résout en un objet contenant les paramètres de route dynamique depuis le segment racine jusqu'à cette mise en page.

export default async function Layout({
  params,
}: {
  params: Promise<{ team: string }>
}) {
  const { team } = await params
}
Exemple de 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'] }>
  • Comme la prop params est une promesse, vous devez utiliser async/await ou la fonction use de React pour accéder aux valeurs.
    • Dans la version 14 et antérieures, params était une prop synchrone. Pour faciliter la rétrocompatibilité, vous pouvez toujours y accéder de manière synchrone dans Next.js 15, mais ce comportement sera déprécié à l'avenir.

Mise en page racine (Root Layout)

Le répertoire app doit inclure une mise en page racine app/layout.js.

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>{children}</body>
    </html>
  )
}
  • La mise en page racine doit définir les balises <html> et <body>.
    • Vous ne devriez pas ajouter manuellement des balises <head> comme <title> et <meta> dans les mises en page racines. À la place, utilisez l'API Metadata qui gère automatiquement les exigences avancées comme le streaming et la déduplication des éléments <head>.
  • Vous pouvez utiliser des groupes de routes pour créer plusieurs mises en page racines.
    • Naviguer entre plusieurs mises en page racines provoquera un rechargement complet de la page (par opposition à une navigation côté client). Par exemple, naviguer de /cart qui utilise app/(shop)/layout.js vers /blog qui utilise app/(marketing)/layout.js provoquera un rechargement complet de la page. Cela s'applique uniquement aux multiples mises en page racines.

Mises en garde

Objet Request

Les mises en page sont mises en cache côté client pendant la navigation pour éviter des requêtes serveur inutiles.

Les Layouts ne sont pas rerendus. Ils peuvent être mis en cache et réutilisés pour éviter des calculs inutiles lors de la navigation entre les pages. En restreignant l'accès des mises en page à la requête brute, Next.js peut empêcher l'exécution de code utilisateur potentiellement lent ou coûteux dans la mise en page, ce qui pourrait nuire aux performances.

Pour accéder à l'objet request, vous pouvez utiliser les API headers et cookies dans les Composants Serveur et les Fonctions.

import { cookies } from 'next/headers'

export default async function Layout({ children }) {
  const cookieStore = await cookies()
  const theme = cookieStore.get('theme')
  return '...'
}

Paramètres de requête (Query params)

Les mises en page ne sont pas rerendues lors de la navigation, elles ne peuvent donc pas accéder aux paramètres de recherche qui deviendraient autrement obsolètes.

Pour accéder aux paramètres de requête mis à jour, vous pouvez utiliser la prop searchParams de la Page, ou les lire dans un Composant Client en utilisant le hook useSearchParams. Comme les Composants Clients sont rerendus lors de la navigation, ils ont accès aux derniers paramètres de requête.

'use client'

import { useSearchParams } from 'next/navigation'

export default function Search() {
  const searchParams = useSearchParams()

  const search = searchParams.get('search')

  return '...'
}

Pathname

Les mises en page ne sont pas rerendues lors de la navigation, elles ne peuvent donc pas accéder au pathname qui deviendrait autrement obsolète.

Pour accéder au pathname actuel, vous pouvez le lire dans un Composant Client en utilisant le hook usePathname. Comme les Composants Clients sont rerendus lors de la navigation, ils ont accès au dernier pathname.

'use client'

import { usePathname } from 'next/navigation'

// Logique simplifiée pour les breadcrumbs
export default function Breadcrumbs() {
  const pathname = usePathname()
  const segments = pathname.split('/')

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

Récupération de données (Fetching Data)

Les mises en page ne peuvent pas transmettre de données à leurs children. Cependant, vous pouvez récupérer les mêmes données dans une route plusieurs fois, et utiliser cache de React pour dédupliquer les requêtes sans affecter les performances.

Alternativement, lorsque vous utilisez fetch dans Next.js, les requêtes sont automatiquement dédupliquées.

export async function getUser(id: string) {
  const res = await fetch(`https://.../users/${id}`)
  return res.json()
}

Accès aux segments enfants

Les mises en page n'ont pas accès aux segments de route en dessous d'elles-mêmes. Pour accéder à tous les segments de route, vous pouvez utiliser useSelectedLayoutSegment ou useSelectedLayoutSegments dans un Composant Client.

'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}`}
      // Change le style selon que le lien est actif ou non
      style={{ fontWeight: isActive ? 'bold' : 'normal' }}
    >
      {children}
    </Link>
  )
}

Exemples

Métadonnées (Metadata)

Vous pouvez modifier les éléments HTML <head> comme title et meta en utilisant l'objet metadata ou la fonction generateMetadata.

import type { Metadata } from 'next'

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

export default function Layout({ children }: { children: React.ReactNode }) {
  return '...'
}

Bon à savoir : Vous ne devriez pas ajouter manuellement des balises <head> comme <title> et <meta> dans les mises en page racines. À la place, utilisez les API Metadata qui gèrent automatiquement les exigences avancées comme le streaming et la déduplication des éléments <head>.

Liens de navigation actifs

Vous pouvez utiliser le hook usePathname pour déterminer si un lien de navigation est actif.

Comme usePathname est un hook client, vous devez extraire les liens de navigation dans un Composant Client, qui peut être importé dans votre mise en page :

'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="/">
        Accueil
      </Link>

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

Affichage de contenu basé sur les params

En utilisant les segments de route dynamiques, vous pouvez afficher ou récupérer du contenu spécifique en fonction de la prop params.

export default async function DashboardLayout({
  children,
  params,
}: {
  children: React.ReactNode
  params: Promise<{ team: string }>
}) {
  const { team } = await params

  return (
    <section>
      <header>
        <h1>Bienvenue sur le tableau de bord de {team}</h1>
      </header>
      <main>{children}</main>
    </section>
  )
}

Lecture des params dans les composants clients

Pour utiliser params dans un composant client (qui ne peut pas être async), vous pouvez utiliser la fonction use de React pour lire la promesse :

'use client'

import { use } from 'react'

export default function Page({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  const { slug } = use(params)
}

Historique des versions

VersionModifications
v15.0.0-RCparams est désormais une promesse. Un codemod est disponible.
v13.0.0layout introduit.