Le guide pour avoir des Intercepting Routes en Next.js qui fonctionnent
09/12/2024 • Melvynx
09/12/2024 • Melvynx
Les Intercepting Routes en Next.js sont très pratiques pour pouvoir afficher des Dialogs au lieu d'afficher une page tout en gérant les informations de la page dans l'URL.

Tu peux voir que quand je clique sur un des produits, ça m'affiche une Dialog et que l'URL devient https://www.producthunt.com/posts/vela-os.
Mais si tu vas directement sur l'URL sans passer par la page, tu vas tomber sur cette page :

Cette fois le produit est affiché en "plein écran" et n'est pas affiché dans la Dialog comme précédemment. C'est la magie des intercepting routes justement.
Pour ça, on va utiliser le combo de 2 fonctionnalités :
Les Parallel Routes permettent de définir des "segments" avec notamment @modal par exemple afin de pouvoir injecter une "page" dans une autre page.
Les Intercepting Routes, elles, vont permettre de venir "intercepter" une requête quand elle est faite dans la navigation interne et d'afficher autre chose à la place, nous, on va justement afficher une Dialog qui sera dans une "Parallel Route".
Imaginons qu'on veut afficher une Dialog pour la route /login au lieu d'afficher la page entière.
Pour ça, on va déjà créer la page standard :
// app/login/page.tsx
export default async function PostPage(props) {
return <div>Login</div>;
}Ensuite, on va pouvoir créer la Parallel Route :
// app/@modal/(.)login/page.tsx
export default async function LoginPage(props) {
return (
<InterceptingDialog>
<div>Login</div>
</InterceptingDialog>
);
}Tu peux aussi créer le fichier InterceptingDialog.tsx qui sera un client component qui vient faire router.back() quand on clique sur le bouton de fermeture de la Dialog.
// app/@modal/InterceptingDialog.tsx
"use client";
import { useRouter } from "next/navigation";
export default function InterceptingDialog({
children,
}: {
children: React.ReactNode;
}) {
const router = useRouter();
return <Dialog onOpenChange={() => router.back()}>{children}</Dialog>;
}Et maintenant, il va falloir intégrer cette Parallel Route dans le layout.tsx de notre application :
// app/layout.tsx
export default function RootLayout({
children,
modal,
}: {
children: React.ReactNode;
modal: React.ReactNode;
}) {
return (
<html>
<body>
{children}
{modal} // [!code ++]
</body>
</html>
);
}De cette manière, cette modal va être "injectée" dans notre layout.tsx si elle affiche quelque chose.
Si ça ne marche pas directement, tu peux relancer le serveur NextJS pour rafraîchir le layout.tsx. J'ai eu quelques problèmes avec ça.
Maintenant, avec le code qu'on a fait jusqu'à maintenant, ça ne va pas fonctionner correctement. Notamment, le fait de fermer la Dialog ne va pas la fermer, elle va rester là. Aussi, quand on va sur des routes comme :
/login/testLa Dialog va aussi s'afficher alors qu'on ne veut qu'elle s'affiche uniquement sur /login.
Pour régler ce problème, il faut ajouter 2 choses :
On va créer un fichier default.tsx afin de pouvoir gérer les routes qui ne sont pas gérées par notre Parallel Route.
// app/@modal/default.tsx
export default function DefaultModal() {
return null;
}Ensuite, on va faire en sorte de venir "catch" toutes les routes qui ne sont pas gérées par notre Parallel Route avec ce qu'on appelle un "Catch All".
// app/@modal/[...catchAll]/page.tsx
export default function CatchAll() {
return null;
}Ce petit bout de code vient faire en sorte que quand on change d'URL et qu'on va sur /login/test, la page se ferme correctement 🎊
En suivant tout ceci, tu devrais avoir le comportement souhaité. Voici un Stackblitz fonctionnel qui suit ce que j'ai présenté :
Si tu veux devenir un pro de NextJS pour créer des applications performantes et optimisées, tu peux te rendre sur ma formation NextJS gratuite.
Tu es très sûrement intéressé aussi par :
On se retrouve là-bas,