Routes parallèles
Les routes parallèles vous permettent d'afficher simultanément ou conditionnellement une ou plusieurs pages dans la même mise en page. Elles sont utiles pour les sections hautement dynamiques d'une application, comme les tableaux de bord et les flux sur les réseaux sociaux.
Par exemple, pour un tableau de bord, vous pouvez utiliser des routes parallèles pour afficher simultanément les pages team
et analytics
:

Emplacements (Slots)
Les routes parallèles sont créées à l'aide d'emplacements nommés. Les emplacements sont définis avec la convention @folder
. Par exemple, la structure de fichiers suivante définit deux emplacements : @analytics
et @team
:

Les emplacements sont passés comme props au layout parent partagé. Pour l'exemple ci-dessus, le composant dans app/layout.js
accepte maintenant les props @analytics
et @team
, et peut les afficher en parallèle avec la prop children
:
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}
</>
)
}
Cependant, les emplacements ne sont pas des segments de route et n'affectent pas la structure de l'URL. Par exemple, pour /@analytics/views
, l'URL sera /views
car @analytics
est un emplacement.
Bon à savoir :
- La prop
children
est un emplacement implicite qui n'a pas besoin d'être mappé à un dossier. Cela signifie queapp/page.js
est équivalent àapp/@children/page.js
.
État actif et navigation
Par défaut, Next.js suit l'état actif (ou la sous-page) pour chaque emplacement. Cependant, le contenu affiché dans un emplacement dépendra du type de navigation :
- Navigation douce : Lors de la navigation côté client, Next.js effectuera un rendu partiel, changeant la sous-page dans l'emplacement, tout en conservant les sous-pages actives des autres emplacements, même si elles ne correspondent pas à l'URL actuelle.
- Navigation complète : Après un chargement complet de page (actualisation du navigateur), Next.js ne peut pas déterminer l'état actif pour les emplacements qui ne correspondent pas à l'URL actuelle. À la place, il affichera un fichier
default.js
pour les emplacements non correspondants, ou404
sidefault.js
n'existe pas.
Bon à savoir :
- Le
404
pour les routes non correspondantes permet de s'assurer que vous n'affichez pas accidentellement une route parallèle sur une page pour laquelle elle n'était pas prévue.
default.js
Vous pouvez définir un fichier default.js
comme solution de repli pour les emplacements non correspondants lors du chargement initial ou d'un rechargement complet de page.
Considérez la structure de dossiers suivante. L'emplacement @team
a une page /settings
, mais @analytics
ne l'a pas.

Lors de la navigation vers /settings
, l'emplacement @team
affichera la page /settings
tout en conservant la page active actuelle pour l'emplacement @analytics
.
Lors d'un rechargement, Next.js affichera un default.js
pour @analytics
. Si default.js
n'existe pas, un 404
est affiché à la place.
De plus, comme children
est un emplacement implicite, vous devez également créer un fichier default.js
pour afficher une solution de repli pour children
lorsque Next.js ne peut pas récupérer l'état actif de la page parente.
useSelectedLayoutSegment(s)
Les fonctions useSelectedLayoutSegment
et useSelectedLayoutSegments
acceptent un paramètre parallelRoutesKey
, qui vous permet de lire le segment de route actif dans un emplacement.
'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')
// ...
}
Lorsqu'un utilisateur navigue vers app/@auth/login
(ou /login
dans la barre d'URL), loginSegment
sera égal à la chaîne "login"
.
Exemples
Routes conditionnelles
Vous pouvez utiliser les routes parallèles pour afficher conditionnellement des routes en fonction de certaines conditions, comme le rôle de l'utilisateur. Par exemple, pour afficher une page de tableau de bord différente pour les rôles /admin
ou /user
:

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}</>
}
Groupes d'onglets
Vous pouvez ajouter un layout
dans un emplacement pour permettre aux utilisateurs de naviguer dans l'emplacement de manière indépendante. C'est utile pour créer des onglets.
Par exemple, l'emplacement @analytics
a deux sous-pages : /page-views
et /visitors
.

Dans @analytics
, créez un fichier layout
pour partager les onglets entre les deux pages :
import Link from 'next/link'
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<nav>
<Link href="/page-views">Vues de page</Link>
<Link href="/visitors">Visiteurs</Link>
</nav>
<div>{children}</div>
</>
)
}
import Link from 'next/link'
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<nav>
<Link href="/page-views">Vues de page</Link>
<Link href="/visitors">Visiteurs</Link>
</nav>
<div>{children}</div>
</>
)
}
Modales
Les routes parallèles peuvent être utilisées avec les routes d'interception pour créer des modales. Cela vous permet de résoudre des défis courants lors de la création de modales, tels que :
- Rendre le contenu de la modale partageable via une URL.
- Préserver le contexte lorsque la page est actualisée, au lieu de fermer la modale.
- Fermer la modale lors d'une navigation arrière plutôt que de revenir à la route précédente.
- Rouvrir la modale lors d'une navigation avant.
Considérez le modèle d'interface utilisateur suivant, où un utilisateur peut ouvrir une modale de connexion à partir d'un layout en utilisant la navigation côté client, ou accéder à une page /login
séparée :

Pour implémenter ce modèle, commencez par créer une route /login
qui affiche votre page de connexion principale.

import { Login } from '@/app/ui/login'
export default function Page() {
return <Login />
}
import { Login } from '@/app/ui/login'
export default function Page() {
return <Login />
}
Ensuite, dans l'emplacement @auth
, ajoutez un fichier default.js
qui retourne null
. Cela garantit que la modale n'est pas affichée lorsqu'elle n'est pas active.
export default function Default() {
return null
}
export default function Default() {
return null
}
Dans votre emplacement @auth
, interceptez la route /login
en mettant à jour le dossier /(.)login
. Importez le composant <Modal>
et ses enfants dans le fichier /(.)login/page.tsx
:
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>
)
}
Bon à savoir :
- La convention utilisée pour intercepter la route, par exemple
(.)
, dépend de votre structure de fichiers. Voir Convention des routes d'interception.- En séparant la fonctionnalité
<Modal>
du contenu de la modale (<Login>
), vous pouvez vous assurer que tout contenu à l'intérieur de la modale, comme les formulaires, sont des composants serveur. Voir Entrelacement des composants client et serveur pour plus d'informations.
Ouverture de la modale
Maintenant, vous pouvez utiliser le routeur Next.js pour ouvrir et fermer la modale. Cela garantit que l'URL est correctement mise à jour lorsque la modale est ouverte, et lors des navigations avant et arrière.
Pour ouvrir la modale, passez l'emplacement @auth
comme prop au layout parent et affichez-le avec la prop children
.
import Link from 'next/link'
export default function Layout({
auth,
children,
}: {
auth: React.ReactNode
children: React.ReactNode
}) {
return (
<>
<nav>
<Link href="/login">Ouvrir la modale</Link>
</nav>
<div>{auth}</div>
<div>{children}</div>
</>
)
}
import Link from 'next/link'
export default function Layout({ auth, children }) {
return (
<>
<nav>
<Link href="/login">Ouvrir la modale</Link>
</nav>
<div>{auth}</div>
<div>{children}</div>
</>
)
}
Lorsque l'utilisateur clique sur le <Link>
, la modale s'ouvrira au lieu de naviguer vers la page /login
. Cependant, lors d'un rechargement ou d'un chargement initial, la navigation vers /login
amènera l'utilisateur à la page de connexion principale.
Fermeture de la modale
Vous pouvez fermer la modale en appelant router.back()
ou en utilisant le composant Link
.
'use client'
import { useRouter } from 'next/navigation'
export function Modal({ children }: { children: React.ReactNode }) {
const router = useRouter()
return (
<>
<button
onClick={() => {
router.back()
}}
>
Fermer la modale
</button>
<div>{children}</div>
</>
)
}
'use client'
import { useRouter } from 'next/navigation'
export function Modal({ children }) {
const router = useRouter()
return (
<>
<button
onClick={() => {
router.back()
}}
>
Fermer la modale
</button>
<div>{children}</div>
</>
)
}
Lorsque vous utilisez le composant Link
pour naviguer vers une page qui ne devrait plus afficher l'emplacement @auth
, nous utilisons une route catch-all qui retourne null
.
import Link from 'next/link'
export function Modal({ children }: { children: React.ReactNode }) {
return (
<>
<Link href="/">Fermer la modale</Link>
<div>{children}</div>
</>
)
}
import Link from 'next/link'
export function Modal({ children }) {
return (
<>
<Link href="/">Fermer la modale</Link>
<div>{children}</div>
</>
)
}
export default function CatchAll() {
return null
}
export default function CatchAll() {
return null
}
Bon à savoir :
- Nous utilisons une route catch-all dans notre emplacement
@auth
pour fermer la modale en raison du comportement décrit dans État actif et navigation. Comme les navigations côté client vers une route qui ne correspond plus à l'emplacement resteront visibles, nous devons faire correspondre l'emplacement à une route qui retournenull
pour fermer la modale.- D'autres exemples pourraient inclure l'ouverture d'une modale photo dans une galerie tout en ayant une page dédiée
/photo/[id]
, ou l'ouverture d'un panier d'achat dans une modale latérale.- Voir un exemple de modales avec des routes interceptées et parallèles.
UI de chargement et d'erreur
Les routes parallèles peuvent être diffusées indépendamment, vous permettant de définir des états d'erreur et de chargement indépendants pour chaque route :

Voir la documentation UI de chargement et Gestion des erreurs pour plus d'informations.
Routes dynamiques
Les routes dynamiques permettent de générer des segments d'URL à partir de données dynamiques de manière programmatique.
Routes d'interception
Utilisez les routes d'interception pour charger une nouvelle route dans la mise en page actuelle tout en masquant l'URL du navigateur, utile pour des motifs de routage avancés comme les modales.