Comment créer des mises en page et des pages

Next.js utilise un routage basé sur le système de fichiers, ce qui signifie que vous pouvez utiliser des dossiers et des fichiers pour définir des routes. Cette page vous guidera dans la création de mises en page et de pages, et comment les lier entre elles.

Création d'une page

Une page est une interface utilisateur rendue sur une route spécifique. Pour créer une page, ajoutez un fichier page dans le répertoire app et exportez par défaut un composant React. Par exemple, pour créer une page d'accueil (/) :

Fichier spécial page.js
export default function Page() {
  return <h1>Hello Next.js!</h1>
}
export default function Page() {
  return <h1>Hello Next.js!</h1>
}

Création d'une mise en page

Une mise en page est une interface utilisateur partagée entre plusieurs pages. Lors de la navigation, les mises en page conservent leur état, restent interactives et ne sont pas re-rendues.

Vous pouvez définir une mise en page en exportant par défaut un composant React depuis un fichier layout. Le composant doit accepter une prop children qui peut être une page ou une autre mise en page.

Par exemple, pour créer une mise en page qui accepte votre page d'accueil comme enfant, ajoutez un fichier layout dans le répertoire app :

Fichier spécial layout.js
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        {/* UI de mise en page */}
        {/* Placez children là où vous voulez rendre une page ou une mise en page imbriquée */}
        <main>{children}</main>
      </body>
    </html>
  )
}
export default function DashboardLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {/* UI de mise en page */}
        {/* Placez children là où vous voulez rendre une page ou une mise en page imbriquée */}
        <main>{children}</main>
      </body>
    </html>
  )
}

La mise en page ci-dessus est appelée mise en page racine car elle est définie à la racine du répertoire app. La mise en page racine est obligatoire et doit contenir les balises html et body.

Création d'une route imbriquée

Une route imbriquée est une route composée de plusieurs segments d'URL. Par exemple, la route /blog/[slug] est composée de trois segments :

  • / (Segment racine)
  • blog (Segment)
  • [slug] (Segment feuille)

Dans Next.js :

  • Les dossiers sont utilisés pour définir les segments de route qui correspondent aux segments d'URL.
  • Les fichiers (comme page et layout) sont utilisés pour créer l'interface utilisateur affichée pour un segment.

Pour créer des routes imbriquées, vous pouvez imbriquer des dossiers les uns dans les autres. Par exemple, pour ajouter une route pour /blog, créez un dossier appelé blog dans le répertoire app. Ensuite, pour rendre /blog accessible publiquement, ajoutez un fichier page.tsx :

Hiérarchie de fichiers montrant un dossier blog et un fichier page.js
// Imports fictifs
import { getPosts } from '@/lib/posts'
import { Post } from '@/ui/post'

export default async function Page() {
  const posts = await getPosts()

  return (
    <ul>
      {posts.map((post) => (
        <Post key={post.id} post={post} />
      ))}
    </ul>
  )
}
// Imports fictifs
import { getPosts } from '@/lib/posts'
import { Post } from '@/ui/post'

export default async function Page() {
  const posts = await getPosts()

  return (
    <ul>
      {posts.map((post) => (
        <Post key={post.id} post={post} />
      ))}
    </ul>
  )
}

Vous pouvez continuer à imbriquer des dossiers pour créer des routes imbriquées. Par exemple, pour créer une route pour un article de blog spécifique, créez un nouveau dossier [slug] dans blog et ajoutez un fichier page :

Hiérarchie de fichiers montrant un dossier blog avec un dossier slug imbriqué et un fichier page.js
function generateStaticParams() {}

export default function Page() {
  return <h1>Hello, Blog Post Page!</h1>
}
function generateStaticParams() {}

export default function Page() {
  return <h1>Hello, Blog Post Page!</h1>
}

Envelopper un nom de dossier entre crochets (par exemple [slug]) crée un segment de route dynamique qui est utilisé pour générer plusieurs pages à partir de données, par exemple des articles de blog, des pages produits, etc.

Imbrication des mises en page

Par défaut, les mises en page dans la hiérarchie des dossiers sont également imbriquées, ce qui signifie qu'elles englobent les mises en page enfants via leur prop children. Vous pouvez imbriquer des mises en page en ajoutant layout dans des segments de route spécifiques (dossiers).

Par exemple, pour créer une mise en page pour la route /blog, ajoutez un nouveau fichier layout dans le dossier blog.

Hiérarchie de fichiers montrant la mise en page racine englobant la mise en page blog
export default function BlogLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return <section>{children}</section>
}
export default function BlogLayout({ children }) {
  return <section>{children}</section>
}

Si vous combinez les deux mises en page ci-dessus, la mise en page racine (app/layout.js) engloberait la mise en page blog (app/blog/layout.js), qui engloberait à son tour la page blog (app/blog/page.js) et la page d'article de blog (app/blog/[slug]/page.js).

Création d'un segment dynamique

Les segments dynamiques vous permettent de créer des routes générées à partir de données. Par exemple, au lieu de créer manuellement une route pour chaque article de blog individuel, vous pouvez créer un segment dynamique pour générer les routes en fonction des données des articles de blog.

Pour créer un segment dynamique, enveloppez le nom du segment (dossier) entre crochets : [segmentName]. Par exemple, dans la route app/blog/[slug]/page.tsx, [slug] est le segment dynamique.

export default async function BlogPostPage({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  const { slug } = await params
  const post = await getPost(slug)

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </div>
  )
}
export default async function BlogPostPage({ params }) {
  const { slug } = await params
  const post = await getPost(slug)

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </div>
  )
}

Apprenez-en plus sur les segments dynamiques.

Liaison entre les pages

Vous pouvez utiliser le composant <Link> pour naviguer entre les routes. <Link> est un composant intégré de Next.js qui étend la balise HTML <a> pour fournir le préchargement et la navigation côté client.

Par exemple, pour générer une liste d'articles de blog, importez <Link> depuis next/link et passez une prop href au composant :

import Link from 'next/link'

export default async function Post({ post }) {
  const posts = await getPosts()

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.slug}>
          <Link href={`/blog/${post.slug}`}>{post.title}</Link>
        </li>
      ))}
    </ul>
  )
}
import Link from 'next/link'

export default async function Post({ post }) {
  const posts = await getPosts()

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.slug}>
          <Link href={`/blog/${post.slug}`}>{post.title}</Link>
        </li>
      ))}
    </ul>
  )
}

Bon à savoir : <Link> est le principal moyen de naviguer entre les routes dans Next.js. Vous pouvez également utiliser le hook useRouter pour une navigation plus avancée.