Introduction/Guides/Formulaires

Comment créer des formulaires avec les API Routes

Les formulaires vous permettent de créer et de mettre à jour des données dans les applications web. Next.js offre une solution puissante pour gérer les mutations de données en utilisant les API Routes. Ce guide vous montrera comment traiter les soumissions de formulaires côté serveur.

Formulaires côté serveur

Pour gérer les soumissions de formulaires côté serveur, créez un point de terminaison d'API pour muter les données de manière sécurisée.

import type { NextApiRequest, NextApiResponse } from 'next'

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const data = req.body
  const id = await createItem(data)
  res.status(200).json({ id })
}

Ensuite, appelez l'API Route depuis le client avec un gestionnaire d'événements :

import { FormEvent } from 'react'

export default function Page() {
  async function onSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()

    const formData = new FormData(event.currentTarget)
    const response = await fetch('/api/submit', {
      method: 'POST',
      body: formData,
    })

    // Traitez la réponse si nécessaire
    const data = await response.json()
    // ...
  }

  return (
    <form onSubmit={onSubmit}>
      <input type="text" name="name" />
      <button type="submit">Submit</button>
    </form>
  )
}

Bon à savoir :

  • Les API Routes ne spécifient pas d'en-têtes CORS, ce qui signifie qu'elles sont par défaut limitées à la même origine.
  • Comme les API Routes s'exécutent côté serveur, nous pouvons utiliser des valeurs sensibles (comme des clés API) via les Variables d'environnement sans les exposer au client. Ceci est crucial pour la sécurité de votre application.

Validation des formulaires

Nous recommandons d'utiliser la validation HTML comme required et type="email" pour une validation de base côté client.

Pour une validation plus avancée côté serveur, vous pouvez utiliser une bibliothèque de validation de schéma comme zod pour valider les champs du formulaire avant de muter les données :

import type { NextApiRequest, NextApiResponse } from 'next'
import { z } from 'zod'

const schema = z.object({
  // ...
})

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const parsed = schema.parse(req.body)
  // ...
}

Gestion des erreurs

Vous pouvez utiliser l'état React pour afficher un message d'erreur en cas d'échec de soumission du formulaire :

import React, { useState, FormEvent } from 'react'

export default function Page() {
  const [isLoading, setIsLoading] = useState<boolean>(false)
  const [error, setError] = useState<string | null>(null)

  async function onSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()
    setIsLoading(true)
    setError(null) // Efface les erreurs précédentes lorsqu'une nouvelle requête démarre

    try {
      const formData = new FormData(event.currentTarget)
      const response = await fetch('/api/submit', {
        method: 'POST',
        body: formData,
      })

      if (!response.ok) {
        throw new Error('Échec de la soumission des données. Veuillez réessayer.')
      }

      // Traitez la réponse si nécessaire
      const data = await response.json()
      // ...
    } catch (error) {
      // Capturez le message d'erreur pour l'afficher à l'utilisateur
      setError(error.message)
      console.error(error)
    } finally {
      setIsLoading(false)
    }
  }

  return (
    <div>
      {error && <div style={{ color: 'red' }}>{error}</div>}
      <form onSubmit={onSubmit}>
        <input type="text" name="name" />
        <button type="submit" disabled={isLoading}>
          {isLoading ? 'Chargement...' : 'Submit'}
        </button>
      </form>
    </div>
  )
}

Affichage de l'état de chargement

Vous pouvez utiliser l'état React pour afficher un état de chargement lors de la soumission d'un formulaire côté serveur :

import React, { useState, FormEvent } from 'react'

export default function Page() {
  const [isLoading, setIsLoading] = useState<boolean>(false)

  async function onSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()
    setIsLoading(true) // Active le chargement lorsque la requête démarre

    try {
      const formData = new FormData(event.currentTarget)
      const response = await fetch('/api/submit', {
        method: 'POST',
        body: formData,
      })

      // Traitez la réponse si nécessaire
      const data = await response.json()
      // ...
    } catch (error) {
      // Gérez l'erreur si nécessaire
      console.error(error)
    } finally {
      setIsLoading(false) // Désactive le chargement lorsque la requête est terminée
    }
  }

  return (
    <form onSubmit={onSubmit}>
      <input type="text" name="name" />
      <button type="submit" disabled={isLoading}>
        {isLoading ? 'Chargement...' : 'Submit'}
      </button>
    </form>
  )
}

Redirection

Si vous souhaitez rediriger l'utilisateur vers une autre route après une mutation, vous pouvez utiliser redirect vers n'importe quelle URL absolue ou relative :

import type { NextApiRequest, NextApiResponse } from 'next'

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const id = await addPost()
  res.redirect(307, `/post/${id}`)
}

On this page