Formulaire

Le composant <Form> étend l'élément HTML <form> pour fournir le préchargement de l'interface de chargement, une navigation côté client lors de la soumission, et une amélioration progressive.

Il est particulièrement utile pour les formulaires qui mettent à jour les paramètres de recherche dans l'URL, car il réduit le code passe-partout nécessaire pour réaliser ce qui précède.

Utilisation de base :

import Form from 'next/form'

export default function Page() {
  return (
    <Form action="/search">
      {/* Lors de la soumission, la valeur de l'input sera ajoutée
          à l'URL, par exemple /search?query=abc */}
      <input name="query" />
      <button type="submit">Submit</button>
    </Form>
  )
}

Référence

Le comportement du composant <Form> dépend du type de la prop action (chaîne de caractères ou fonction).

  • Lorsque action est une chaîne de caractères, le <Form> se comporte comme un formulaire HTML natif utilisant la méthode GET. Les données du formulaire sont encodées dans l'URL sous forme de paramètres de recherche, et lors de la soumission, il navigue vers l'URL spécifiée. De plus, Next.js :
    • Précharge le chemin lorsque le formulaire devient visible, ce qui précharge l'interface partagée (par exemple layout.js et loading.js), résultant en une navigation plus rapide.
    • Effectue une navigation côté client au lieu d'un rechargement complet de la page lors de la soumission du formulaire. Cela préserve l'interface partagée et l'état côté client.
  • Lorsque action est une fonction (Action Serveur), <Form> se comporte comme un formulaire React, exécutant l'action lors de la soumission du formulaire.

Props action (chaîne de caractères)

Lorsque action est une chaîne de caractères, le composant <Form> prend en charge les props suivantes :

PropExempleTypeRequis
actionaction="/search"string (URL ou chemin relatif)Oui
replacereplace={false}boolean-
scrollscroll={true}boolean-
prefetchprefetch={true}boolean-
  • action : L'URL ou le chemin vers lequel naviguer lors de la soumission du formulaire.
    • Une chaîne vide "" naviguera vers la même route avec les paramètres de recherche mis à jour.
  • replace : Remplace l'état actuel de l'historique au lieu d'en ajouter un nouveau à la pile d'historique du navigateur. Par défaut false.
  • scroll : Contrôle le comportement de défilement lors de la navigation. Par défaut true, ce qui signifie qu'il fera défiler vers le haut de la nouvelle route et maintiendra la position de défilement pour les navigations avant et arrière.
  • prefetch : Contrôle si le chemin doit être préchargé lorsque le formulaire devient visible dans la fenêtre de l'utilisateur. Par défaut true.

Props action (fonction)

Lorsque action est une fonction, le composant <Form> prend en charge la prop suivante :

PropExempleTypeRequis
actionaction={myAction}function (Action Serveur)Oui
  • action : L'Action Serveur à appeler lors de la soumission du formulaire. Voir la documentation React pour plus d'informations.

Bon à savoir : Lorsque action est une fonction, les props replace et scroll sont ignorées.

Mises en garde

  • formAction : Peut être utilisé dans un <button> ou <input type="submit"> pour remplacer la prop action. Next.js effectuera une navigation côté client, cependant, cette approche ne prend pas en charge le préchargement.
    • Lors de l'utilisation de basePath, vous devez également l'inclure dans le chemin formAction. Par exemple formAction="/base-path/search".
  • key : Passer une prop key à une action de type chaîne de caractères n'est pas pris en charge. Si vous souhaitez déclencher un nouveau rendu ou effectuer une mutation, envisagez d'utiliser une action de type fonction à la place.
  • onSubmit : Peut être utilisé pour gérer la logique de soumission du formulaire. Cependant, appeler event.preventDefault() remplacera le comportement de <Form>, comme la navigation vers l'URL spécifiée.
  • method, encType, target : Ne sont pas pris en charge car ils remplacent le comportement de <Form>.
    • De même, formMethod, formEncType et formTarget peuvent être utilisés pour remplacer respectivement les props method, encType et target, et leur utilisation reviendra au comportement natif du navigateur.
    • Si vous avez besoin d'utiliser ces props, utilisez plutôt l'élément HTML <form>.
  • <input type="file"> : L'utilisation de ce type d'input lorsque action est une chaîne de caractères correspondra au comportement du navigateur en soumettant le nom du fichier au lieu de l'objet fichier.

Exemples

Formulaire de recherche menant à une page de résultats

Vous pouvez créer un formulaire de recherche qui navigue vers une page de résultats en passant le chemin comme action :

import Form from 'next/form'

export default function Page() {
  return (
    <Form action="/search">
      <input name="query" />
      <button type="submit">Submit</button>
    </Form>
  )
}

Lorsque l'utilisateur met à jour le champ de recherche et soumet le formulaire, les données du formulaire seront encodées dans l'URL sous forme de paramètres de recherche, par exemple /search?query=abc.

Bon à savoir : Si vous passez une chaîne vide "" à action, le formulaire naviguera vers la même route avec les paramètres de recherche mis à jour.

Sur la page des résultats, vous pouvez accéder à la requête en utilisant la prop searchParams de page.js et l'utiliser pour récupérer des données depuis une source externe.

import { getSearchResults } from '@/lib/search'

export default async function SearchPage({
  searchParams,
}: {
  searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}) {
  const results = await getSearchResults((await searchParams).query)

  return <div>...</div>
}

Lorsque le <Form> devient visible dans la fenêtre de l'utilisateur, l'interface partagée (comme layout.js et loading.js) sur la page /search sera préchargée. Lors de la soumission, le formulaire naviguera immédiatement vers la nouvelle route et affichera l'interface de chargement pendant que les résultats sont récupérés. Vous pouvez concevoir l'interface de secours en utilisant loading.js :

export default function Loading() {
  return <div>Loading...</div>
}

Pour couvrir les cas où l'interface partagée n'est pas encore chargée, vous pouvez afficher un retour instantané à l'utilisateur en utilisant useFormStatus.

Tout d'abord, créez un composant qui affiche un état de chargement lorsque le formulaire est en attente :

'use client'
import { useFormStatus } from 'react-dom'

export default function SearchButton() {
  const status = useFormStatus()
  return (
    <button type="submit">{status.pending ? 'Recherche en cours...' : 'Rechercher'}</button>
  )
}

Ensuite, mettez à jour la page du formulaire de recherche pour utiliser le composant SearchButton :

import Form from 'next/form'
import { SearchButton } from '@/ui/search-button'

export default function Page() {
  return (
    <Form action="/search">
      <input name="query" />
      <SearchButton />
    </Form>
  )
}

Mutations avec Actions Serveur

Vous pouvez effectuer des mutations en passant une fonction à la prop action.

import Form from 'next/form'
import { createPost } from '@/posts/actions'

export default function Page() {
  return (
    <Form action={createPost}>
      <input name="title" />
      {/* ... */}
      <button type="submit">Créer un article</button>
    </Form>
  )
}

Après une mutation, il est courant de rediriger vers la nouvelle ressource. Vous pouvez utiliser la fonction redirect de next/navigation pour naviguer vers la nouvelle page d'article.

Bon à savoir : Comme la "destination" de la soumission du formulaire n'est pas connue avant l'exécution de l'action, <Form> ne peut pas précharger automatiquement l'interface partagée.

'use server'
import { redirect } from 'next/navigation'

export async function createPost(formData: FormData) {
  // Créer un nouvel article
  // ...

  // Rediriger vers le nouvel article
  redirect(`/posts/${data.id}`)
}

Ensuite, dans la nouvelle page, vous pouvez récupérer les données en utilisant la prop params :

import { getPost } from '@/posts/data'

export default async function PostPage({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
  const data = await getPost(id)

  return (
    <div>
      <h1>{data.title}</h1>
      {/* ... */}
    </div>
  )
}

Consultez la documentation Actions Serveur pour plus d'exemples.

On this page