Entdecken Sie das Response-Streaming von React Server Actions für progressive Formularantworten. Erfahren Sie, wie Sie schnellere, reaktionsfähigere Formulare für eine bessere User Experience erstellen.
React Server Action Response-Streaming: Progressive Formularantworten für eine verbesserte UX
React Server Actions führen einen leistungsstarken Paradigmenwechsel in der Handhabung serverseitiger Operationen in unseren React-Anwendungen ein. Eine der spannendsten Funktionen ist die Möglichkeit, Antworten progressiv zu streamen. Dies ermöglicht es uns, den Nutzern sofortiges Feedback zu geben, noch bevor die gesamte Operation abgeschlossen ist. Dies ist besonders vorteilhaft für Formulare, bei denen wir eine reaktionsfähigere und ansprechendere User Experience schaffen können, indem wir die Benutzeroberfläche aktualisieren, sobald Daten verfügbar werden.
React Server Actions verstehen
Server Actions sind asynchrone Funktionen, die auf dem Server ausgeführt und von React-Komponenten initiiert werden. Sie bieten mehrere Vorteile gegenüber herkömmlichen API-Aufrufen:
- Verbesserte Sicherheit: Server Actions werden direkt auf dem Server ausgeführt, was das Risiko verringert, sensible Daten oder Logik dem Client preiszugeben.
- Weniger Boilerplate-Code: Sie eliminieren die Notwendigkeit für separate API-Routen und Datenabruflogik auf dem Client.
- Verbesserte Leistung: Sie können serverseitiges Rendering (SSR) und Caching für schnellere Ladezeiten und eine verbesserte Performance nutzen.
- Typsicherheit: Mit TypeScript bieten Server Actions eine durchgehende Typsicherheit und gewährleisten die Datenkonsistenz zwischen Client und Server.
Die Stärke des Response-Streamings
Herkömmliche Formularübermittlungen beinhalten oft das Senden aller Daten an den Server, das Warten auf eine Antwort und die anschließende Aktualisierung der Benutzeroberfläche. Dies kann zu einer wahrgenommenen Verzögerung führen, insbesondere bei komplexen Formularen oder langsamen Netzwerkverbindungen. Response-Streaming ermöglicht es dem Server, Daten in Teilen an den Client zurückzusenden, sodass wir die Benutzeroberfläche progressiv aktualisieren können, sobald Daten verfügbar werden.
Stellen Sie sich ein Formular vor, das einen komplexen Preis basierend auf der Benutzereingabe berechnet. Anstatt auf den Abschluss der gesamten Berechnung zu warten, kann der Server Zwischenergebnisse an den Client streamen und dem Benutzer so Echtzeit-Feedback geben. Dies kann die User Experience erheblich verbessern und die Anwendung reaktionsfähiger wirken lassen.
Implementierung progressiver Formularantworten mit Server Actions
Lassen Sie uns ein Beispiel durchgehen, wie man progressive Formularantworten mit React Server Actions implementiert.
Beispiel: Ein Echtzeit-Währungsumrechner
Wir erstellen ein einfaches Währungsumrechner-Formular, das Echtzeit-Wechselkursaktualisierungen bereitstellt, während der Benutzer den Betrag eingibt.
1. Die Server Action einrichten
Zuerst definieren wir die Server Action, die die Währungsumrechnung durchführt.
// server/actions.ts
'use server';
import { unstable_cache } from 'next/cache';
async function getExchangeRate(fromCurrency: string, toCurrency: string): Promise<number> {
// Simulieren des Abrufs des Wechselkurses von einer externen API
console.log(`Fetching exchange rate for ${fromCurrency} to ${toCurrency}`);
await new Promise(resolve => setTimeout(resolve, 500)); // Netzwerkverzögerung simulieren
if (fromCurrency === 'USD' && toCurrency === 'EUR') return 0.92;
if (fromCurrency === 'EUR' && toCurrency === 'USD') return 1.09;
if (fromCurrency === 'USD' && toCurrency === 'JPY') return 145;
if (fromCurrency === 'JPY' && toCurrency === 'USD') return 0.0069;
throw new Error(`Exchange rate not found for ${fromCurrency} to ${toCurrency}`);
}
export const convertCurrency = async (prevState: any, formData: FormData) => {
const fromCurrency = formData.get('fromCurrency') as string;
const toCurrency = formData.get('toCurrency') as string;
const amount = Number(formData.get('amount'));
try {
if (!fromCurrency || !toCurrency || isNaN(amount)) {
return { message: 'Please provide valid input.' };
}
// Simulieren des Streamings der Antwort
await new Promise(resolve => setTimeout(resolve, 250));
const exchangeRate = await unstable_cache(
async () => getExchangeRate(fromCurrency, toCurrency),
[`exchange-rate-${fromCurrency}-${toCurrency}`],
{ tags: [`exchange-rate-${fromCurrency}-${toCurrency}`] }
)();
await new Promise(resolve => setTimeout(resolve, 250));
const convertedAmount = amount * exchangeRate;
return { message: `Converted amount: ${convertedAmount.toFixed(2)} ${toCurrency}` };
} catch (e: any) {
console.error(e);
return { message: 'Failed to convert currency.' };
}
};
In diesem Beispiel ruft die convertCurrency
Server Action den Wechselkurs ab (simuliert mit einer Verzögerung) und berechnet den umgerechneten Betrag. Wir haben künstliche Verzögerungen mit setTimeout
hinzugefügt, um Netzwerklatenz zu simulieren und den Streaming-Effekt zu demonstrieren.
2. Die React-Komponente implementieren
Als Nächstes erstellen wir die React-Komponente, die die Server Action verwendet.
// app/page.tsx
'use client';
import { useState, useTransition } from 'react';
import { convertCurrency } from './server/actions';
import { useFormState } from 'react-dom';
export default function CurrencyConverter() {
const [fromCurrency, setFromCurrency] = useState('USD');
const [toCurrency, setToCurrency] = useState('EUR');
const [amount, setAmount] = useState('');
const [isPending, startTransition] = useTransition();
const [state, formAction] = useFormState(convertCurrency, { message: '' });
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
startTransition(() => {
formAction(new FormData(event.target as HTMLFormElement));
});
};
return (
<div>
<h2>Echtzeit-Währungsumrechner</h2>
<form action={handleSubmit}>
<label htmlFor="fromCurrency">Von:</label>
<select id="fromCurrency" name="fromCurrency" value={fromCurrency} onChange={(e) => setFromCurrency(e.target.value)}>
<option value="USD">USD</option>
<option value="EUR">EUR</option>
<option value="JPY">JPY</option>
</select>
<label htmlFor="toCurrency">Nach:</label>
<select id="toCurrency" name="toCurrency" value={toCurrency} onChange={(e) => setToCurrency(e.target.value)}>
<option value="EUR">EUR</option>
<option value="USD">USD</option>
<option value="JPY">JPY</option>
</select>
<label htmlFor="amount">Betrag:</label>
<input
type="number"
id="amount"
name="amount"
value={amount}
onChange={(e) => setAmount(e.target.value)}
/>
<button type="submit" disabled={isPending}>
{isPending ? 'Wird umgerechnet...' : 'Umrechnen'}
</button>
</form>
<p>{state.message}</p>
</div>
);
}
Wichtige Punkte:
- Wir verwenden den
useFormState
-Hook, um den Formularzustand zu verwalten und die Server Action aufzurufen. - Der
isPending
-Zustand vonuseTransition
deaktiviert den Senden-Button und zeigt eine "Wird umgerechnet..."-Nachricht an, während die Aktion läuft, um dem Benutzer Feedback zu geben. - Die von
useFormState
zurückgegebeneformAction
-Funktion kümmert sich automatisch um die Formularübermittlung und aktualisiert den Zustand mit der Antwort der Server Action.
3. Die progressiven Updates verstehen
Wenn der Benutzer das Formular abschickt, wird die handleSubmit
-Funktion aufgerufen. Sie erstellt ein FormData
-Objekt aus dem Formular und übergibt es an die formAction
-Funktion. Die Server Action wird dann auf dem Server ausgeführt. Aufgrund der künstlichen Verzögerungen, die in der Server Action eingeführt wurden, werden Sie Folgendes beobachten:
- Der Senden-Button ändert sich fast sofort zu "Wird umgerechnet...".
- Nach einer kurzen Verzögerung (250ms) simuliert der Code das Abrufen des Wechselkurses.
- Der umgerechnete Betrag wird berechnet und das Ergebnis an den Client zurückgesendet.
- Die
state.message
in der React-Komponente wird aktualisiert und zeigt den umgerechneten Betrag an.
Dies demonstriert, wie uns Response-Streaming ermöglicht, dem Benutzer Zwischen-Updates bereitzustellen, sobald Daten verfügbar sind, was zu einer reaktionsfähigeren und ansprechenderen User Experience führt.
Vorteile von progressiven Formularantworten
- Verbesserte User Experience: Bietet den Nutzern sofortiges Feedback, wodurch sich die Anwendung reaktionsfähiger und weniger träge anfühlt.
- Reduzierte wahrgenommene Latenz: Durch die Anzeige von Zwischenergebnissen nehmen die Nutzer den Prozess als schneller wahr, auch wenn die gesamte Operation genauso lange dauert.
- Gesteigertes Engagement: Hält die Nutzer durch Echtzeit-Updates bei der Stange und verhindert, dass sie das Formular aufgrund wahrgenommener Verzögerungen verlassen.
- Erhöhte Konversionsraten: Eine reibungslosere und reaktionsfähigere User Experience kann zu höheren Konversionsraten führen, insbesondere bei komplexen Formularen.
Fortgeschrittene Techniken
1. Verwendung von `useOptimistic` für sofortige UI-Updates
Der useOptimistic
-Hook ermöglicht es Ihnen, die Benutzeroberfläche optimistisch zu aktualisieren, bevor die Server Action abgeschlossen ist. Dies kann eine noch schneller wahrgenommene Reaktionszeit bieten, da die Benutzeroberfläche sofort das erwartete Ergebnis widerspiegelt.
import { useOptimistic } from 'react';
function MyComponent() {
const [optimisticState, addOptimistic] = useOptimistic(
initialState,
(state, newUpdate) => {
// Gibt den neuen Zustand basierend auf dem Update zurück
return { ...state, ...newUpdate };
}
);
const handleClick = async () => {
addOptimistic({ someValue: 'optimistic update' });
await myServerAction();
};
return (
<div>
<p>{optimisticState.someValue}</p>
<button onClick={handleClick}>Aktualisieren</button>
</div>
);
}
Im Beispiel des Währungsumrechners könnten Sie den umgerechneten Betrag optimistisch auf Basis des aktuellen Wechselkurses aktualisieren und dem Benutzer so eine sofortige Vorschau geben, bevor die eigentliche Berechnung auf dem Server abgeschlossen ist. Wenn der Server einen Fehler zurückgibt, können Sie das optimistische Update rückgängig machen.
2. Implementierung von Fehlerbehandlung und Fallback-Mechanismen
Es ist entscheidend, eine robuste Fehlerbehandlung und Fallback-Mechanismen zu implementieren, um Fälle zu behandeln, in denen die Server Action fehlschlägt oder die Netzwerkverbindung unterbrochen wird. Sie können den try...catch
-Block innerhalb der Server Action verwenden, um Fehler abzufangen und eine entsprechende Fehlermeldung an den Client zurückzugeben.
// server/actions.ts
export const convertCurrency = async (prevState: any, formData: FormData) => {
// ...
try {
// ...
} catch (error: any) {
console.error(error);
return { message: 'An error occurred while converting the currency. Please try again later.' };
}
};
Auf der Client-Seite können Sie dem Benutzer die Fehlermeldung anzeigen und Optionen zum erneuten Versuch der Operation oder zur Kontaktaufnahme mit dem Support anbieten.
3. Caching von Wechselkursen zur Leistungssteigerung
Das Abrufen von Wechselkursen von einer externen API kann ein Leistungsengpass sein. Um die Leistung zu verbessern, können Sie die Wechselkurse mithilfe eines Caching-Mechanismus wie Redis oder Memcached zwischenspeichern. Die unstable_cache
-Funktion von Next.js (wie im Beispiel verwendet) bietet eine integrierte Caching-Lösung. Denken Sie daran, den Cache regelmäßig zu invalidieren, um sicherzustellen, dass die Wechselkurse aktuell sind.
4. Überlegungen zur Internationalisierung
Beim Erstellen von Anwendungen für ein globales Publikum ist es wichtig, die Internationalisierung (i18n) zu berücksichtigen. Dies umfasst:
- Zahlenformatierung: Verwenden Sie geeignete Zahlenformate für verschiedene Gebietsschemata (z. B. Kommas oder Punkte als Dezimaltrennzeichen).
- Währungsformatierung: Zeigen Sie Währungssymbole und -formate entsprechend dem Gebietsschema des Benutzers an.
- Datums- und Zeitformatierung: Verwenden Sie geeignete Datums- und Zeitformate für verschiedene Gebietsschemata.
- Lokalisierung: Übersetzen Sie die Benutzeroberfläche in verschiedene Sprachen.
Bibliotheken wie Intl
und react-intl
können Ihnen bei der Implementierung von i18n in Ihren React-Anwendungen helfen.
Praxisbeispiele und Anwendungsfälle
- E-Commerce: Anzeige von Echtzeit-Versandkosten und Lieferschätzungen, während der Benutzer Artikel zum Warenkorb hinzufügt.
- Finanzanwendungen: Bereitstellung von Echtzeit-Aktienkursen und Portfolio-Updates.
- Reisebuchung: Anzeige von Echtzeit-Flugpreisen und -verfügbarkeiten.
- Datenvisualisierung: Streamen von Datenaktualisierungen für Diagramme und Graphen.
- Kollaborationstools: Anzeige von Echtzeit-Updates für Dokumente und Projekte.
Fazit
Das Response-Streaming von React Server Actions bietet eine leistungsstarke Möglichkeit, die User Experience Ihrer React-Anwendungen zu verbessern. Durch die Bereitstellung progressiver Formularantworten können Sie schnellere, reaktionsfähigere und ansprechendere Formulare erstellen, die die Nutzer bei der Stange halten und die Konversionsraten verbessern. Durch die Kombination von Response-Streaming mit Techniken wie optimistischen Updates und Caching können Sie wirklich außergewöhnliche Benutzererlebnisse schaffen.
Da sich React Server Actions ständig weiterentwickeln, können wir erwarten, dass noch leistungsfähigere Funktionen und Möglichkeiten entstehen, die die Entwicklung komplexer und dynamischer Webanwendungen weiter vereinfachen.
Weiterführende Informationen
Diese Anleitung bietet einen umfassenden Überblick über das Response-Streaming von React Server Actions und seine Anwendung auf progressive Formularantworten. Indem Sie die hier besprochenen Konzepte und Techniken verstehen, können Sie diese leistungsstarke Funktion nutzen, um schnellere, reaktionsfähigere und ansprechendere Webanwendungen zu erstellen.