Server Actions und Mutationen
Server Actions sind asynchrone Funktionen, die auf dem Server ausgeführt werden. Sie können in Server- und Client-Komponenten verwendet werden, um Formularübermittlungen und Datenmutationen in Next.js-Anwendungen zu handhaben.
🎥 Video: Mehr über Formulare und Mutationen mit Server Actions erfahren → YouTube (10 Minuten).
Konvention
Eine Server Action kann mit der React "use server"
-Direktive definiert werden. Sie können die Direktive am Anfang einer async
-Funktion platzieren, um die Funktion als Server Action zu markieren, oder am Anfang einer separaten Datei, um alle Exporte dieser Datei als Server Actions zu markieren.
Server-Komponenten
Server-Komponenten können die Inline-Funktions- oder Modul-Ebene der "use server"
-Direktive verwenden. Um eine Server Action inline zu definieren, fügen Sie "use server"
am Anfang des Funktionskörpers hinzu:
// Server-Komponente
export default function Page() {
// Server Action
async function create() {
'use server'
// ...
}
return (
// ...
)
}
// Server-Komponente
export default function Page() {
// Server Action
async function create() {
'use server'
// ...
}
return (
// ...
)
}
Client-Komponenten
Client-Komponenten können nur Actions importieren, die die Modul-Ebene der "use server"
-Direktive verwenden.
Um eine Server Action in einer Client-Komponente aufzurufen, erstellen Sie eine neue Datei und fügen Sie die "use server"
-Direktive am Anfang hinzu. Alle Funktionen innerhalb der Datei werden als Server Actions markiert, die sowohl in Client- als auch Server-Komponenten wiederverwendet werden können:
'use server'
export async function create() {
// ...
}
'use server'
export async function create() {
// ...
}
Sie können eine Server Action auch als Prop an eine Client-Komponente übergeben:
<ClientComponent updateItem={updateItem} />
'use client'
export default function ClientComponent({ updateItem }) {
return <form action={updateItem}>{/* ... */}</form>
}
Verhalten
- Server Actions können mit dem
action
-Attribut in einem<form>
-Element aufgerufen werden:- Server-Komponenten unterstützen standardmäßig progressive Verbesserung, d.h. das Formular wird auch dann übermittelt, wenn JavaScript noch nicht geladen oder deaktiviert ist.
- In Client-Komponenten werden Formulare, die Server Actions aufrufen, in eine Warteschlange gestellt, falls JavaScript noch nicht geladen ist, wobei die Client-Hydration priorisiert wird.
- Nach der Hydration wird der Browser bei der Formularübermittlung nicht neu geladen.
- Server Actions sind nicht auf
<form>
beschränkt und können von Event-Handlern,useEffect
, Drittanbieter-Bibliotheken und anderen Formularelementen wie<button>
aufgerufen werden. - Server Actions integrieren sich in die Next.js Caching- und Revalidierungsarchitektur. Wenn eine Action aufgerufen wird, kann Next.js sowohl die aktualisierte UI als auch neue Daten in einem einzigen Server-Roundtrip zurückgeben.
- Hinter den Kulissen verwenden Actions die
POST
-Methode, und nur diese HTTP-Methode kann sie aufrufen. - Die Argumente und Rückgabewerte von Server Actions müssen von React serialisierbar sein. Siehe die React-Dokumentation für eine Liste der serialisierbaren Argumente und Werte.
- Server Actions sind Funktionen. Das bedeutet, sie können überall in Ihrer Anwendung wiederverwendet werden.
- Server Actions erben die Laufzeitumgebung von der Seite oder dem Layout, in dem sie verwendet werden.
- Server Actions erben die Route Segment Config von der Seite oder dem Layout, in dem sie verwendet werden, einschließlich Feldern wie
maxDuration
.
Beispiele
Formulare
React erweitert das HTML <form>
-Element, um Server Actions mit der action
-Prop aufrufen zu können.
Bei Aufruf in einem Formular erhält die Action automatisch das FormData
-Objekt. Sie müssen React useState
nicht verwenden, um Felder zu verwalten, sondern können die Daten mit den nativen FormData
-Methoden extrahieren:
export default function Page() {
async function createInvoice(formData: FormData) {
'use server'
const rawFormData = {
customerId: formData.get('customerId'),
amount: formData.get('amount'),
status: formData.get('status'),
}
// Daten mutieren
// Cache revalidieren
}
return <form action={createInvoice}>...</form>
}
export default function Page() {
async function createInvoice(formData) {
'use server'
const rawFormData = {
customerId: formData.get('customerId'),
amount: formData.get('amount'),
status: formData.get('status'),
}
// Daten mutieren
// Cache revalidieren
}
return <form action={createInvoice}>...</form>
}
Gut zu wissen:
- Beispiel: Formular mit Lade- und Fehlerzuständen
- Bei Formularen mit vielen Feldern können Sie die
entries()
-Methode mit JavaScriptsObject.fromEntries()
verwenden. Zum Beispiel:const rawFormData = Object.fromEntries(formData)
. Beachten Sie, dass dasformData
zusätzliche$ACTION_
-Eigenschaften enthält.- Siehe React
<form>
-Dokumentation für mehr Informationen.
Zusätzliche Argumente übergeben
Sie können zusätzliche Argumente an eine Server Action übergeben, indem Sie die JavaScript bind
-Methode verwenden.
'use client'
import { updateUser } from './actions'
export function UserProfile({ userId }: { userId: string }) {
const updateUserWithId = updateUser.bind(null, userId)
return (
<form action={updateUserWithId}>
<input type="text" name="name" />
<button type="submit">Benutzernamen aktualisieren</button>
</form>
)
}
'use client'
import { updateUser } from './actions'
export function UserProfile({ userId }) {
const updateUserWithId = updateUser.bind(null, userId)
return (
<form action={updateUserWithId}>
<input type="text" name="name" />
<button type="submit">Benutzernamen aktualisieren</button>
</form>
)
}
Die Server Action erhält das userId
-Argument zusätzlich zu den Formulardaten:
'use server'
export async function updateUser(userId, formData) {
// ...
}
Gut zu wissen:
- Eine Alternative ist, Argumente als versteckte Eingabefelder im Formular zu übergeben (z.B.
<input type="hidden" name="userId" value={userId} />
). Der Wert wird jedoch Teil des gerenderten HTML und ist nicht kodiert..bind
funktioniert sowohl in Server- als auch Client-Komponenten. Es unterstützt auch progressive Verbesserung.
Ausstehende Zustände
Sie können den React useFormStatus
-Hook verwenden, um einen ausstehenden Zustand anzuzeigen, während das Formular übermittelt wird.
useFormStatus
gibt den Status für ein bestimmtes<form>
zurück, daher muss es als Kind des<form>
-Elements definiert werden.useFormStatus
ist ein React-Hook und muss daher in einer Client-Komponente verwendet werden.
<SubmitButton />
kann dann in jedes Formular eingebettet werden:
import { SubmitButton } from '@/app/submit-button'
import { createItem } from '@/app/actions'
// Server-Komponente
export default async function Home() {
return (
<form action={createItem}>
<input type="text" name="field-name" />
<SubmitButton />
</form>
)
}
import { SubmitButton } from '@/app/submit-button'
import { createItem } from '@/app/actions'
// Server-Komponente
export default async function Home() {
return (
<form action={createItem}>
<input type="text" name="field-name" />
<SubmitButton />
</form>
)
}
Serverseitige Validierung und Fehlerbehandlung
Wir empfehlen die Verwendung von HTML-Validierung wie required
und type="email"
für grundlegende clientseitige Formularvalidierung.
Für erweiterte serverseitige Validierung können Sie eine Bibliothek wie zod verwenden, um die Formularfelder vor der Datenmutation zu validieren:
'use server'
import { z } from 'zod'
const schema = z.object({
email: z.string({
invalid_type_error: 'Ungültige E-Mail',
}),
})
export default async function createUser(formData: FormData) {
const validatedFields = schema.safeParse({
email: formData.get('email'),
})
// Frühzeitig zurückkehren, wenn die Formulardaten ungültig sind
if (!validatedFields.success) {
return {
errors: validatedFields.error.flatten().fieldErrors,
}
}
// Daten mutieren
}
'use server'
import { z } from 'zod'
const schema = z.object({
email: z.string({
invalid_type_error: 'Ungültige E-Mail',
}),
})
export default async function createsUser(formData) {
const validatedFields = schema.safeParse({
email: formData.get('email'),
})
// Frühzeitig zurückkehren, wenn die Formulardaten ungültig sind
if (!validatedFields.success) {
return {
errors: validatedFields.error.flatten().fieldErrors,
}
}
// Daten mutieren
}
Sobald die Felder auf dem Server validiert wurden, können Sie ein serialisierbares Objekt in Ihrer Action zurückgeben und den React useFormState
-Hook verwenden, um dem Benutzer eine Nachricht anzuzeigen.
- Durch das Übergeben der Action an
useFormState
ändert sich die Funktionssignatur der Action, um einen neuenprevState
- oderinitialState
-Parameter als erstes Argument zu erhalten. useFormState
ist ein React-Hook und muss daher in einer Client-Komponente verwendet werden.
'use server'
export async function createUser(prevState: any, formData: FormData) {
// ...
return {
message: 'Bitte geben Sie eine gültige E-Mail ein',
}
}
'use server'
export async function createUser(prevState, formData) {
// ...
return {
message: 'Bitte geben Sie eine gültige E-Mail ein',
}
}
Dann können Sie Ihre Action an den useFormState
-Hook übergeben und den zurückgegebenen state
verwenden, um eine Fehlermeldung anzuzeigen.
'use client'
import { useFormState } from 'react-dom'
import { createUser } from '@/app/actions'
const initialState = {
message: '',
}
export function Signup() {
const [state, formAction] = useFormState(createUser, initialState)
return (
<form action={formAction}>
<label htmlFor="email">E-Mail</label>
<input type="text" id="email" name="email" required />
{/* ... */}
<p aria-live="polite" className="sr-only">
{state?.message}
</p>
<button>Registrieren</button>
</form>
)
}
'use client'
import { useFormState } from 'react-dom'
import { createUser } from '@/app/actions'
const initialState = {
message: '',
}
export function Signup() {
const [state, formAction] = useFormState(createUser, initialState)
return (
<form action={formAction}>
<label htmlFor="email">E-Mail</label>
<input type="text" id="email" name="email" required />
{/* ... */}
<p aria-live="polite" className="sr-only">
{state?.message}
</p>
<button>Registrieren</button>
</form>
)
}
Gut zu wissen:
- Bevor Sie Daten mutieren, sollten Sie immer sicherstellen, dass ein Benutzer auch berechtigt ist, die Aktion durchzuführen. Siehe Authentifizierung und Autorisierung.
Optimistische Updates
Sie können den React useOptimistic
-Hook verwenden, um die UI optimistisch zu aktualisieren, bevor die Server Action abgeschlossen ist, anstatt auf die Antwort zu warten:
'use client'
import { useOptimistic } from 'react'
import { send } from './actions'
type Message = {
message: string
}
export function Thread({ messages }: { messages: Message[] }) {
const [optimisticMessages, addOptimisticMessage] = useOptimistic<
Message[],
string
>(messages, (state, newMessage) => [...state, { message: newMessage }])
return (
<div>
{optimisticMessages.map((m, k) => (
<div key={k}>{m.message}</div>
))}
<form
action={async (formData: FormData) => {
const message = formData.get('message')
addOptimisticMessage(message)
await send(message)
}}
>
<input type="text" name="message" />
<button type="submit">Senden</button>
</form>
</div>
)
}
'use client'
import { useOptimistic } from 'react'
import { send } from './actions'
export function Thread({ messages }) {
const [optimisticMessages, addOptimisticMessage] = useOptimistic(
messages,
(state, newMessage) => [...state, { message: newMessage }]
)
return (
<div>
{optimisticMessages.map((m) => (
<div>{m.message}</div>
))}
<form
action={async (formData) => {
const message = formData.get('message')
addOptimisticMessage(message)
await send(message)
}}
>
<input type="text" name="message" />
<button type="submit">Senden</button>
</form>
</div>
)
}
Verschachtelte Elemente
Sie können eine Server Action in Elementen aufrufen, die in <form>
verschachtelt sind, wie <button>
, <input type="submit">
und <input type="image">
. Diese Elemente akzeptieren die formAction
-Prop oder Event-Handler.
Dies ist nützlich, wenn Sie mehrere Server Actions innerhalb eines Formulars aufrufen möchten. Beispielsweise können Sie ein spezifisches <button>
-Element zum Speichern eines Post-Entwurfs zusätzlich zum Veröffentlichen erstellen. Siehe die React <form>
-Dokumentation für weitere Informationen.
Programmgesteuerte Formularübermittlung
Sie können eine Formularübermittlung mit der Methode requestSubmit()
auslösen. Zum Beispiel können Sie auf das onKeyDown
-Ereignis hören, wenn der Benutzer ⌘
+ Enter
drückt:
'use client'
export function Entry() {
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (
(e.ctrlKey || e.metaKey) &&
(e.key === 'Enter' || e.key === 'NumpadEnter')
) {
e.preventDefault()
e.currentTarget.form?.requestSubmit()
}
}
return (
<div>
<textarea name="entry" rows={20} required onKeyDown={handleKeyDown} />
</div>
)
}
'use client'
export function Entry() {
const handleKeyDown = (e) => {
if (
(e.ctrlKey || e.metaKey) &&
(e.key === 'Enter' || e.key === 'NumpadEnter')
) {
e.preventDefault()
e.currentTarget.form?.requestSubmit()
}
}
return (
<div>
<textarea name="entry" rows={20} required onKeyDown={handleKeyDown} />
</div>
)
}
Dies löst die Übermittlung des nächstgelegenen <form>
-Vorfahrenelements aus, wodurch die Server-Aktion aufgerufen wird.
Nicht-Formular-Elemente
Während Server-Aktionen häufig innerhalb von <form>
-Elementen verwendet werden, können sie auch aus anderen Teilen Ihres Codes wie Event-Handlern und useEffect
aufgerufen werden.
Event-Handler
Sie können eine Server-Aktion aus Event-Handlern wie onClick
aufrufen. Zum Beispiel, um einen Like-Zähler zu erhöhen:
Um die Benutzererfahrung zu verbessern, empfehlen wir die Verwendung anderer React-APIs wie useOptimistic
und useTransition
, um die Benutzeroberfläche zu aktualisieren, bevor die Server-Aktion auf dem Server abgeschlossen ist, oder um einen ausstehenden Zustand anzuzeigen.
Sie können auch Event-Handler zu Formularelementen hinzufügen, zum Beispiel, um ein Formularfeld onChange
zu speichern:
'use client'
import { publishPost, saveDraft } from './actions'
export default function EditPost() {
return (
<form action={publishPost}>
<textarea
name="content"
onChange={async (e) => {
await saveDraft(e.target.value)
}}
/>
<button type="submit">Publish</button>
</form>
)
}
Für solche Fälle, in denen mehrere Ereignisse in schneller Folge ausgelöst werden können, empfehlen wir Debouncing, um unnötige Aufrufe von Server-Aktionen zu vermeiden.
useEffect
Sie können den React-Hook useEffect
verwenden, um eine Server-Aktion aufzurufen, wenn die Komponente eingebunden wird oder eine Abhängigkeit sich ändert. Dies ist nützlich für Mutationen, die von globalen Ereignissen abhängen oder automatisch ausgelöst werden müssen. Zum Beispiel onKeyDown
für App-Shortcuts, ein Intersection Observer-Hook für unendliches Scrollen oder wenn die Komponente eingebunden wird, um eine Aufrufzahl zu aktualisieren:
'use client'
import { incrementViews } from './actions'
import { useState, useEffect } from 'react'
export default function ViewCount({ initialViews }: { initialViews: number }) {
const [views, setViews] = useState(initialViews)
useEffect(() => {
const updateViews = async () => {
const updatedViews = await incrementViews()
setViews(updatedViews)
}
updateViews()
}, [])
return <p>Total Views: {views}</p>
}
'use client'
import { incrementViews } from './actions'
import { useState, useEffect } from 'react'
export default function ViewCount({ initialViews }: { initialViews: number }) {
const [views, setViews] = useState(initialViews)
useEffect(() => {
const updateViews = async () => {
const updatedViews = await incrementViews()
setViews(updatedViews)
}
updateViews()
}, [])
return <p>Total Views: {views}</p>
}
Denken Sie daran, die Verhaltensweisen und Einschränkungen von useEffect
zu beachten.
Fehlerbehandlung
Wenn ein Fehler auftritt, wird er vom nächsten error.js
oder <Suspense>
-Boundary auf dem Client abgefangen. Wir empfehlen die Verwendung von try/catch
, um Fehler zurückzugeben, die von Ihrer Benutzeroberfläche behandelt werden können.
Zum Beispiel könnte Ihre Server-Aktion Fehler bei der Erstellung eines neuen Elements behandeln, indem sie eine Nachricht zurückgibt:
'use server'
export async function createTodo(prevState: any, formData: FormData) {
try {
// Daten mutieren
} catch (e) {
throw new Error('Failed to create task')
}
}
'use server'
export async function createTodo(prevState, formData) {
try {
// Daten mutieren
} catch (e) {
throw new Error('Failed to create task')
}
}
Gut zu wissen:
- Neben dem Auslösen des Fehlers können Sie auch ein Objekt zurückgeben, das von
useFormState
behandelt wird. Siehe Serverseitige Validierung und Fehlerbehandlung.
Daten neu validieren
Sie können den Next.js Cache innerhalb Ihrer Server-Aktionen mit der revalidatePath
-API neu validieren:
'use server'
import { revalidatePath } from 'next/cache'
export async function createPost() {
try {
// ...
} catch (error) {
// ...
}
revalidatePath('/posts')
}
'use server'
import { revalidatePath } from 'next/cache'
export async function createPost() {
try {
// ...
} catch (error) {
// ...
}
revalidatePath('/posts')
}
Oder Sie können einen bestimmten Datenabruf mit einem Cache-Tag über revalidateTag
ungültig machen:
'use server'
import { revalidateTag } from 'next/cache'
export async function createPost() {
try {
// ...
} catch (error) {
// ...
}
revalidateTag('posts')
}
'use server'
import { revalidateTag } from 'next/cache'
export async function createPost() {
try {
// ...
} catch (error) {
// ...
}
revalidateTag('posts')
}
Umleitung
Wenn Sie den Benutzer nach Abschluss einer Server-Aktion zu einer anderen Route weiterleiten möchten, können Sie die redirect
-API verwenden. redirect
muss außerhalb des try/catch
-Blocks aufgerufen werden:
'use server'
import { redirect } from 'next/navigation'
import { revalidateTag } from 'next/cache'
export async function createPost(id: string) {
try {
// ...
} catch (error) {
// ...
}
revalidateTag('posts') // Cache für Beiträge aktualisieren
redirect(`/post/${id}`) // Zur neuen Beitragsseite navigieren
}
'use server'
import { redirect } from 'next/navigation'
import { revalidateTag } from 'next/cache'
export async function createPost(id) {
try {
// ...
} catch (error) {
// ...
}
revalidateTag('posts') // Cache für Beiträge aktualisieren
redirect(`/post/${id}`) // Zur neuen Beitragsseite navigieren
}
Cookies
Sie können Cookies innerhalb einer Server-Aktion mit der cookies
-API get
, set
und delete
:
'use server'
import { cookies } from 'next/headers'
export async function exampleAction() {
// Cookie abrufen
const value = cookies().get('name')?.value
// Cookie setzen
cookies().set('name', 'Delba')
// Cookie löschen
cookies().delete('name')
}
'use server'
import { cookies } from 'next/headers'
export async function exampleAction() {
// Cookie abrufen
const value = cookies().get('name')?.value
// Cookie setzen
cookies().set('name', 'Delba')
// Cookie löschen
cookies().delete('name')
}
Siehe weitere Beispiele zum Löschen von Cookies aus Server-Aktionen.
Sicherheit
Authentifizierung und Autorisierung
Sie sollten Server-Aktionen wie öffentlich zugängliche API-Endpunkte behandeln und sicherstellen, dass der Benutzer berechtigt ist, die Aktion auszuführen. Zum Beispiel:
'use server'
import { auth } from './lib'
export function addItem() {
const { user } = auth()
if (!user) {
throw new Error('You must be signed in to perform this action')
}
// ...
}
Closures und Verschlüsselung
Das Definieren einer Server-Aktion innerhalb einer Komponente erstellt einen Closure, in dem die Aktion Zugriff auf den Gültigkeitsbereich der äußeren Funktion hat. Zum Beispiel hat die publish
-Aktion Zugriff auf die Variable publishVersion
:
export default function Page() {
const publishVersion = await getLatestVersion();
async function publish(formData: FormData) {
"use server";
if (publishVersion !== await getLatestVersion()) {
throw new Error('The version has changed since pressing publish');
}
...
}
return <button action={publish}>Publish</button>;
}
export default function Page() {
const publishVersion = await getLatestVersion();
async function publish() {
"use server";
if (publishVersion !== await getLatestVersion()) {
throw new Error('The version has changed since pressing publish');
}
...
}
return <button action={publish}>Publish</button>;
}
Closures sind nützlich, wenn Sie eine Momentaufnahme von Daten (z.B. publishVersion
) zum Zeitpunkt des Renderings erfassen müssen, um sie später beim Aufruf der Aktion verwenden zu können.
Damit dies funktioniert, werden die erfassten Variablen jedoch an den Client und zurück an den Server gesendet, wenn die Aktion aufgerufen wird. Um zu verhindern, dass sensible Daten dem Client preisgegeben werden, verschlüsselt Next.js die geschlossenen Variablen automatisch. Für jede Aktion wird bei jedem Build einer Next.js-Anwendung ein neuer privater Schlüssel generiert. Dies bedeutet, dass Aktionen nur für einen bestimmten Build aufgerufen werden können.
Gut zu wissen: Wir empfehlen nicht, sich allein auf die Verschlüsselung zu verlassen, um zu verhindern, dass sensible Werte dem Client preisgegeben werden. Stattdessen sollten Sie die React taint APIs verwenden, um proaktiv zu verhindern, dass bestimmte Daten an den Client gesendet werden.
Überschreiben von Verschlüsselungsschlüsseln (fortgeschritten)
Wenn Sie Ihre Next.js-Anwendung selbst auf mehreren Servern hosten, kann jeder Serverinstanz ein anderer Verschlüsselungsschlüssel zugewiesen werden, was zu potenziellen Inkonsistenzen führen kann.
Um dies zu vermeiden, können Sie den Verschlüsselungsschlüssel mit der Umgebungsvariable process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY
überschreiben. Durch die Angabe dieser Variable wird sichergestellt, dass Ihre Verschlüsselungsschlüssel über Builds hinweg bestehen bleiben und alle Serverinstanzen denselben Schlüssel verwenden.
Dies ist ein fortgeschrittener Anwendungsfall, bei dem ein konsistentes Verschlüsselungsverhalten über mehrere Bereitstellungen hinweg für Ihre Anwendung entscheidend ist. Sie sollten Standard-Sicherheitspraktiken wie Schlüsselrotation und Signierung berücksichtigen.
Gut zu wissen: Next.js-Anwendungen, die auf Vercel bereitgestellt werden, handhaben dies automatisch.
Erlaubte Ursprünge (fortgeschritten)
Da Server-Aktionen in einem <form>
-Element aufgerufen werden können, sind sie für CSRF-Angriffe anfällig.
Im Hintergrund verwenden Server-Aktionen die POST
-Methode, und nur diese HTTP-Methode ist für ihren Aufruf erlaubt. Dies verhindert die meisten CSRF-Schwachstellen in modernen Browsern, insbesondere da SameSite-Cookies standardmäßig aktiviert sind.
Als zusätzlichen Schutz vergleichen Server-Aktionen in Next.js auch den Origin-Header mit dem Host-Header (oder X-Forwarded-Host
). Wenn diese nicht übereinstimmen, wird die Anfrage abgebrochen. Mit anderen Worten: Server-Aktionen können nur auf demselben Host aufgerufen werden wie die Seite, die sie hostet.
Für große Anwendungen, die Reverse Proxies oder mehrschichtige Backend-Architekturen verwenden (bei denen der Server-API sich von der Produktionsdomäne unterscheidet), wird empfohlen, die Konfigurationsoption serverActions.allowedOrigins
zu verwenden, um eine Liste sicherer Ursprünge anzugeben. Die Option akzeptiert ein Array von Strings.
/** @type {import('next').NextConfig} */
module.exports = {
experimental: {
serverActions: {
allowedOrigins: ['my-proxy.com', '*.my-proxy.com'],
},
},
}
Erfahren Sie mehr über Sicherheit und Server-Aktionen.
Zusätzliche Ressourcen
Weitere Informationen zu Server-Aktionen finden Sie in den folgenden React-Dokumenten: