Routes parallèles

Le routage parallèle vous permet d'afficher simultanément ou conditionnellement une ou plusieurs pages dans la même mise en page. Pour les sections hautement dynamiques d'une application, comme les tableaux de bord et les flux sur les réseaux sociaux, le routage parallèle peut être utilisé pour implémenter des modèles de routage complexes.

Par exemple, vous pouvez afficher simultanément les pages d'équipe et d'analytique.

Diagramme des routes parallèles

Le routage parallèle vous permet de définir des états d'erreur et de chargement indépendants pour chaque route, car elles sont diffusées indépendamment.

Les routes parallèles permettent des états d'erreur et de chargement personnalisés

Le routage parallèle vous permet également d'afficher conditionnellement un emplacement (slot) en fonction de certaines conditions, comme l'état d'authentification. Cela permet d'avoir un code entièrement séparé sur la même URL.

Diagramme des routes conditionnelles

Convention

Les routes parallèles sont créées à l'aide d'emplacements nommés (named slots). Les emplacements sont définis avec la convention @dossier et sont passés à la mise en page de même niveau en tant que props.

Les emplacements ne sont pas des segments de route et n'affectent pas la structure de l'URL. Le chemin de fichier /@team/members serait accessible via /members.

Par exemple, la structure de fichiers suivante définit deux emplacements explicites : @analytics et @team.

Structure du système de fichiers des routes parallèles

La structure de dossiers ci-dessus signifie que le composant dans app/layout.js accepte maintenant les props d'emplacement @analytics et @team, et peut les afficher en parallèle avec la prop children :

export default function Layout(props: {
  children: React.ReactNode
  analytics: React.ReactNode
  team: React.ReactNode
}) {
  return (
    <>
      {props.children}
      {props.team}
      {props.analytics}
    </>
  )
}
export default function Layout(props) {
  return (
    <>
      {props.children}
      {props.team}
      {props.analytics}
    </>
  )
}

Bon à savoir : La prop children est un emplacement implicite qui n'a pas besoin d'être mappé à un dossier. Cela signifie que app/page.js est équivalent à app/@children/page.js.

Routes non correspondantes

Par défaut, le contenu affiché dans un emplacement correspond à l'URL actuelle.

Dans le cas d'un emplacement non correspondant, le contenu affiché par Next.js diffère selon la technique de routage et la structure des dossiers.

default.js

Vous pouvez définir un fichier default.js à afficher comme solution de repli lorsque Next.js ne peut pas récupérer l'état actif d'un emplacement en fonction de l'URL actuelle.

Considérez la structure de dossiers suivante. L'emplacement @team a un répertoire settings, mais pas @analytics.

Routes parallèles non correspondantes

Lors de la navigation, Next.js affichera l'état actif précédent de l'emplacement, même s'il ne correspond pas à l'URL actuelle.

Rechargement

Lors d'un rechargement, Next.js essaiera d'abord d'afficher le fichier default.js de l'emplacement non correspondant. Si celui-ci n'est pas disponible, une 404 est affichée.

La 404 pour les routes non correspondantes permet de s'assurer que vous n'affichez pas accidentellement une route qui ne devrait pas être affichée en parallèle.

useSelectedLayoutSegment(s)

Les fonctions useSelectedLayoutSegment et useSelectedLayoutSegments acceptent une parallelRoutesKey, qui vous permet de lire le segment de route actif dans cet emplacement.

'use client'

import { useSelectedLayoutSegment } from 'next/navigation'

export default async function Layout(props: {
  //...
  auth: React.ReactNode
}) {
  const loginSegments = useSelectedLayoutSegment('auth')
  // ...
}
'use client'

import { useSelectedLayoutSegment } from 'next/navigation'

export default async function Layout(props) {
  const loginSegments = useSelectedLayoutSegment('auth')
  // ...
}

Lorsqu'un utilisateur navigue vers @auth/login, ou /login dans la barre d'URL, loginSegments sera égal à la chaîne "login".

Exemples

Modales

Le routage parallèle peut être utilisé pour afficher des modales.

Diagramme des routes parallèles

L'emplacement @auth affiche un composant <Modal> qui peut être montré en naviguant vers une route correspondante, par exemple /login.

export default async function Layout(props: {
  // ...
  auth: React.ReactNode
}) {
  return (
    <>
      {/* ... */}
      {props.auth}
    </>
  )
}
export default async function Layout(props) {
  return (
    <>
      {/* ... */}
      {props.auth}
    </>
  )
}
import { Modal } from 'components/modal'

export default function Login() {
  return (
    <Modal>
      <h1>Connexion</h1>
      {/* ... */}
    </Modal>
  )
}
import { Modal } from 'components/modal'

export default function Login() {
  return (
    <Modal>
      <h1>Connexion</h1>
      {/* ... */}
    </Modal>
  )
}

Pour vous assurer que le contenu de la modale ne s'affiche pas lorsqu'elle n'est pas active, vous pouvez créer un fichier default.js qui retourne null.

export default function Default() {
  return null
}
export default function Default() {
  return null
}

Fermer une modale

Si une modale a été initiée via une navigation côté client, par exemple en utilisant <Link href="/login">, vous pouvez fermer la modale en appelant router.back() ou en utilisant un composant Link.

'use client'
import { useRouter } from 'next/navigation'
import { Modal } from 'components/modal'

export default async function Login() {
  const router = useRouter()
  return (
    <Modal>
      <span onClick={() => router.back()}>Fermer la modale</span>
      <h1>Connexion</h1>
      ...
    </Modal>
  )
}
'use client'
import { useRouter } from 'next/navigation'
import { Modal } from 'components/modal'

export default async function Login() {
  const router = useRouter()
  return (
    <Modal>
      <span onClick={() => router.back()}>Fermer la modale</span>
      <h1>Connexion</h1>
      ...
    </Modal>
  )
}

Plus d'informations sur les modales sont couvertes dans la section Interception de routes.

Si vous souhaitez naviguer ailleurs et fermer une modale, vous pouvez également utiliser une route attrape-tout (catch-all).

Diagramme des routes parallèles
export default function CatchAll() {
  return null
}
export default function CatchAll() {
  return null
}

Les routes attrape-tout ont priorité sur default.js.

Routes conditionnelles

Les routes parallèles peuvent être utilisées pour implémenter un routage conditionnel. Par exemple, vous pouvez afficher une route @dashboard ou @login en fonction de l'état d'authentification.

import { getUser } from '@/lib/auth'

export default function Layout({
  dashboard,
  login,
}: {
  dashboard: React.ReactNode
  login: React.ReactNode
}) {
  const isLoggedIn = getUser()
  return isLoggedIn ? dashboard : login
}
import { getUser } from '@/lib/auth'

export default function Layout({ dashboard, login }) {
  const isLoggedIn = getUser()
  return isLoggedIn ? dashboard : login
}
Exemple d'authentification avec routes parallèles