Next.jsRouting

Routing

App Router

Next.js apporte un routing basé sur le filsystem de votre projet, ce qui va vous permettre de créer des routes assez simplement.
Tout va se passer dans le dossier /app de votre projet désormais.
Chaque dossier correspond à un segment de votre route, ce qui vous permettra de définir des sous routes en créant des dossiers imbriqués.

Supposons que nous sommes en train de créer une web app avec un dashboard utilisateur qui inclut une section profil et une autre section paramètre.
La structure de votre dossier ressemblera alors à ça:

/app
  /dashboard
    /settings
      page.tsx
    /profile
      page.tsx

Chaque fichier page.tsx exporte un composant React via un export default.
Par exemple le contenu de settings/page.tsx ressemblera à:

app/dashboard/settings/page.tsx
export default function SettingsPage() {
  return <h1>User Settings</h1>
}

Route groups

Next.js met à disposition les route groups qui sont en fait des groupe de routes qui échappe au système de routing par dossier. On les distingue par les parenthèse qui entourent le nom du dossier. Les Route groupssont utiles pour grouper des routes de manière logique sans avoir un impact sur la route.

Ajoutons un groupe (admin).

/app
  /(admin)
    /dashboard
      /settings
        page.tsx
      /profile
        page.tsx

On observe que le dossier /(admin) n’a aucun impact sur l’URL.

Fichiers spéciaux

Next.js permet également d’autres fichiers que page.tsx fournir un comportement unique aux routes, comme layout.tsx pour partager une même squelette de page entre les routes, loading.tsx pour afficher un loader, et error.tsx pour la gestion des erreurs.

Routing dynamique

Next.js propose de créer des routes dynamiques.
Pour définir un segment dynamique d’une route on entoure le nom du dossier par des crochets (par exemple [folderName]).

Pour l’exemple du blog avec des articles (posts) on aurait quelque chose comme app/blog/[slug]/page.tsx.
La partie [slug] est la partie dynamique représentant un un article.
Elle est alors passé en paramètre du composant:

export default async function Post(params: { params: Promise<{slug: string}> }) {
  const { slug } = await params
  return <div>{params.slug}</div>;
}

SSG avec l’App Router

On peut continuer de faire du SSG avec l’app Router de la même manière que le getStaticPaths que nous avons vu plus tôt, on peut maintenant utiliser la méthode generateStaticParams.

export async function generateStaticParams() {
  const posts = await fetch('https://api.vercel.app/blog').then((res) => res.json())
 
  return posts.map((post) => ({
    slug: post.id,
  }))
}
 
export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params
  // ...
}

Bon à savoir

dynamicParams

On peut exporter la constante dynamicParams segment pour controler ce qui se passe lorsqu’un segment qui n’était pas présent lors de la phase de build est visité.

export const dynamicParams = true 

Par défaut il est à true et génère les nouvelles pages à la demande.
Lorsque vous le passez à false, les pages non connus renvoient une 404.

ISR

Vous devez retourner un tableau vide depuis la fonction generateStaticParams ou exporter une constante dynamique de la manière suivante pour revalider les paths au runtime:

export const dynamic = 'force-static'

Catch all

Pour rendre les routes encore plus dynamique on peut catcher non pas seulement un seul segment d’une route mais une portion de la route.

Supposons qu’on est en train de créer un e-commerce avec plusieurs niveau de catégorie. On peut alors utiliser un catch-all segment pour matcher ces catégories (imbriquées ou non).
Le fichier page.tsx devra être dans un dossier nommé de la manière suivante: app/shop/[...categories]/page.tsx.
On pourra alors piloter plusieurs pages à plusieurs niveau avec un seul composant.
Par exemple on pourrait avoir des routes comme /shop/clothes, /shop/clothes/tops, /shop/clothes/tops/t-shirts et toutes les piloter via un seul composant.

export default async function Category({params}: {params: Promise<{categories: string[]}>}) {
  // params.categories est un tableau de categories ['clothes', 'tops', 't-shirts']
  return (
    <div>
      {params.categories.join(',')}
    </div>
  );
}

On peut aussi inclure la route source /shop en utilisant une syntaxe un tout petit peu différente au niveau du nom du dossier: app/shop/[[...categories]]/page.tsx.