Menu

Formulare und Mutationen

Formulare ermöglichen es Ihnen, Daten in Webanwendungen zu erstellen und zu aktualisieren. Next.js bietet eine leistungsstarke Möglichkeit, Formularübermittlungen und Datenänderungen mithilfe von API-Routen zu behandeln.

Hinweis:

  • Wir werden bald empfehlen, den App Router schrittweise zu übernehmen und Server-Aktionen für die Behandlung von Formularübermittlungen und Datenänderungen zu verwenden. Server-Aktionen ermöglichen es Ihnen, asynchrone Serverfunktionen zu definieren, die direkt aus Ihren Komponenten aufgerufen werden können, ohne manuell eine API-Route zu erstellen.
  • API-Routen definieren keine CORS-Header, was bedeutet, dass sie standardmäßig nur für den gleichen Ursprung gelten.
  • Da API-Routen auf dem Server laufen, können wir sensible Werte (wie API-Schlüssel) über Umgebungsvariablen verwenden, ohne sie dem Client preiszugeben. Dies ist entscheidend für die Sicherheit Ihrer Anwendung.

Beispiele

Serverexklusives Formular

Mit dem Pages Router müssen Sie manuell API-Endpunkte erstellen, um Datenänderungen auf dem Server sicher zu behandeln.

pages/api/submit.ts
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 })
}
pages/api/submit.js
export default function handler(req, res) {
  const data = req.body
  const id = await createItem(data)
  res.status(200).json({ id })
}

Rufen Sie dann die API-Route vom Client mit einem Ereignishandler auf:

pages/index.tsx
TypeScript
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,
    })
 
    // Antwort bei Bedarf behandeln
    const data = await response.json()
    // ...
  }
 
  return (
    <form onSubmit={onSubmit}>
      <input type="text" name="name" />
      <button type="submit">Absenden</button>
    </form>
  )
}

Formularvalidierung

Wir empfehlen, HTML-Validierung wie required und type="email" für eine einfache clientseitige Formularvalidierung zu verwenden.

Für eine fortgeschrittenere serverseitige Validierung können Sie eine Schema-Validierungsbibliothek wie zod verwenden, um die Formularfelder vor der Datenänderung zu validieren:

pages/api/submit.ts
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)
  // ...
}
pages/api/submit.js
import { z } from 'zod'
 
const schema = z.object({
  // ...
})
 
export default async function handler(req, res) {
  const parsed = schema.parse(req.body)
  // ...
}

Fehlerbehandlung

Sie können den React-Zustand verwenden, um eine Fehlermeldung anzuzeigen, wenn die Formularübermittlung fehlschlägt:

pages/index.tsx
TypeScript
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) // Vorherige Fehler löschen, wenn eine neue Anfrage beginnt
 
    try {
      const formData = new FormData(event.currentTarget)
      const response = await fetch('/api/submit', {
        method: 'POST',
        body: formData,
      })
 
      if (!response.ok) {
        throw new Error('Daten konnten nicht übermittelt werden. Bitte versuchen Sie es erneut.')
      }
 
      // Antwort bei Bedarf behandeln
      const data = await response.json()
      // ...
    } catch (error) {
      // Fehlermeldung erfassen, um sie dem Benutzer anzuzeigen
      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 ? 'Laden...' : 'Absenden'}
        </button>
      </form>
    </div>
  )
}

Ladezustand anzeigen

Sie können den React-Zustand verwenden, um einen Ladezustand anzuzeigen, während ein Formular auf dem Server übermittelt wird:

pages/index.tsx
TypeScript
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) // Ladezustand beim Start der Anfrage auf true setzen
 
    try {
      const formData = new FormData(event.currentTarget)
      const response = await fetch('/api/submit', {
        method: 'POST',
        body: formData,
      })
 
      // Antwort bei Bedarf behandeln
      const data = await response.json()
      // ...
    } catch (error) {
      // Fehler bei Bedarf behandeln
      console.error(error)
    } finally {
      setIsLoading(false) // Ladezustand beim Abschluss der Anfrage auf false setzen
    }
  }
 
  return (
    <form onSubmit={onSubmit}>
      <input type="text" name="name" />
      <button type="submit" disabled={isLoading}>
        {isLoading ? 'Laden...' : 'Absenden'}
      </button>
    </form>
  )
}

Umleitung

Wenn Sie den Benutzer nach einer Mutation auf eine andere Route weiterleiten möchten, können Sie zu einer absoluten oder relativen URL umleiten:

pages/api/submit.ts
import type { NextApiRequest, NextApiResponse } from 'next'
 
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const id = await addPost()
  res.redirect(307, `/post/${id}`)
}
pages/api/submit.js
export default async function handler(req, res) {
  const id = await addPost()
  res.redirect(307, `/post/${id}`)
}

Cookies setzen

Sie können Cookies in einer API-Route mithilfe der setHeader-Methode der Antwort setzen:

pages/api/cookie.ts
import type { NextApiRequest, NextApiResponse } from 'next'
 
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  res.setHeader('Set-Cookie', 'username=lee; Path=/; HttpOnly')
  res.status(200).send('Cookie wurde gesetzt.')
}
pages/api/cookie.js
export default async function handler(req, res) {
  res.setHeader('Set-Cookie', 'username=lee; Path=/; HttpOnly')
  res.status(200).send('Cookie wurde gesetzt.')
}

Cookies lesen

Sie können Cookies in einer API-Route mithilfe des cookies Request-Helpers lesen:

pages/api/cookie.ts
import type { NextApiRequest, NextApiResponse } from 'next'
 
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const auth = req.cookies.authorization
  // ...
}
pages/api/cookie.js
export default async function handler(req, res) {
  const auth = req.cookies.authorization
  // ...
}

Cookies löschen

Sie können Cookies in einer API-Route mithilfe der setHeader-Methode der Antwort löschen:

pages/api/cookie.ts
import type { NextApiRequest, NextApiResponse } from 'next'
 
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  res.setHeader('Set-Cookie', 'username=; Path=/; HttpOnly; Max-Age=0')
  res.status(200).send('Cookie wurde gelöscht.')
}
pages/api/cookie.js
export default async function handler(req, res) {
  res.setHeader('Set-Cookie', 'username=; Path=/; HttpOnly; Max-Age=0')
  res.status(200).send('Cookie wurde gelöscht.')
}