Explorez le streaming de réponse des Server Actions React pour des réponses de formulaire progressives. Apprenez à créer des formulaires plus rapides et réactifs pour une meilleure expérience utilisateur.
Streaming de Réponse des Server Actions React : Réponse Progressive de Formulaire pour une UX Améliorée
Les Server Actions de React introduisent un puissant changement de paradigme dans la manière dont nous gérons les opérations côté serveur au sein de nos applications React. L'une des fonctionnalités les plus intéressantes est la capacité de streamer les réponses progressivement, nous permettant de fournir un retour immédiat aux utilisateurs avant même que l'opération entière ne soit terminée. Ceci est particulièrement bénéfique pour les formulaires, où nous pouvons créer une expérience utilisateur plus réactive et engageante en mettant à jour l'interface utilisateur à mesure que les données deviennent disponibles.
Comprendre les Server Actions React
Les Server Actions sont des fonctions asynchrones qui s'exécutent sur le serveur, initiées depuis des composants React. Elles offrent plusieurs avantages par rapport aux appels d'API traditionnels :
- Sécurité améliorée : Les Server Actions s'exécutent directement sur le serveur, réduisant le risque d'exposer des données ou une logique sensibles au client.
- Réduction du code répétitif : Elles éliminent le besoin de routes d'API distinctes et de logique de récupération de données côté client.
- Performance accrue : Elles peuvent tirer parti du rendu côté serveur (SSR) et de la mise en cache pour des temps de chargement initiaux plus rapides et des performances améliorées.
- Typage sécurisé : Avec TypeScript, les Server Actions fournissent une sécurité de type de bout en bout, garantissant la cohérence des données entre le client et le serveur.
La Puissance du Streaming de Réponse
Les soumissions de formulaires traditionnelles impliquent souvent d'envoyer toutes les données au serveur, d'attendre une réponse, puis de mettre à jour l'interface utilisateur en conséquence. Cela peut entraîner un délai perçu, en particulier pour les formulaires complexes ou les connexions réseau lentes. Le streaming de réponse permet au serveur d'envoyer des données au client par fragments, nous permettant de mettre à jour l'interface utilisateur progressivement à mesure que les données deviennent disponibles.
Imaginez un formulaire qui calcule un prix complexe en fonction de la saisie de l'utilisateur. Au lieu d'attendre que le calcul complet soit terminé, le serveur peut streamer les résultats intermédiaires vers le client, offrant un retour en temps réel à l'utilisateur. Cela peut améliorer considérablement l'expérience utilisateur et donner à l'application une sensation de plus grande réactivité.
Implémenter une Réponse de Formulaire Progressive avec les Server Actions
Passons en revue un exemple de la manière d'implémenter une réponse de formulaire progressive avec les Server Actions de React.
Exemple : Un Convertisseur de Devises en Temps Réel
Nous allons créer un formulaire simple de convertisseur de devises qui fournit des mises à jour de taux de change en temps réel à mesure que l'utilisateur saisit le montant.
1. Mettre en place la Server Action
D'abord, nous définissons la Server Action qui gère la conversion de devises.
// server/actions.ts
'use server';
import { unstable_cache } from 'next/cache';
async function getExchangeRate(fromCurrency: string, toCurrency: string): Promise<number> {
// Simulate fetching exchange rate from an external API
console.log(`Fetching exchange rate for ${fromCurrency} to ${toCurrency}`);
await new Promise(resolve => setTimeout(resolve, 500)); // Simulate network delay
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.' };
}
// Simulate streaming the response
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.' };
}
};
Dans cet exemple, la Server Action convertCurrency
récupère le taux de change (simulé avec un délai) et calcule le montant converti. Nous avons ajouté des délais artificiels avec setTimeout
pour simuler la latence du réseau et démontrer l'effet de streaming.
2. Implémenter le Composant React
Ensuite, nous créons le composant React qui utilise la Server Action.
// 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>Real-Time Currency Converter</h2>
<form action={handleSubmit}>
<label htmlFor="fromCurrency">From:</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">To:</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">Amount:</label>
<input
type="number"
id="amount"
name="amount"
value={amount}
onChange={(e) => setAmount(e.target.value)}
/>
<button type="submit" disabled={isPending}>
{isPending ? 'Converting...' : 'Convert'}
</button>
</form>
<p>{state.message}</p>
</div>
);
}
Points clés :
- Nous utilisons le hook
useFormState
pour gérer l'état du formulaire et invoquer la Server Action. - L'état
isPending
deuseTransition
désactive le bouton de soumission et affiche un message "Converting..." pendant que l'action est en cours, donnant un retour à l'utilisateur. - La fonction
formAction
renvoyée paruseFormState
gère automatiquement la soumission du formulaire et met à jour l'état avec la réponse de la Server Action.
3. Comprendre les Mises Ă Jour Progressives
Lorsque l'utilisateur soumet le formulaire, la fonction handleSubmit
est appelée. Elle crée un objet FormData
Ă partir du formulaire et le passe Ă la fonction formAction
. La Server Action s'exécute alors sur le serveur. En raison des délais artificiels introduits dans la Server Action, vous observerez ce qui suit :
- Le bouton de soumission passe à "Converting..." presque immédiatement.
- Après un court délai (250ms), le code simule l'obtention du taux de change.
- Le montant converti est calculé et le résultat est renvoyé au client.
- Le
state.message
dans le composant React est mis Ă jour, affichant le montant converti.
Cela démontre comment le streaming de réponse nous permet de fournir des mises à jour intermédiaires à l'utilisateur à mesure que les données deviennent disponibles, conduisant à une expérience utilisateur plus réactive et engageante.
Avantages de la Réponse de Formulaire Progressive
- Expérience utilisateur améliorée : Fournit un retour immédiat aux utilisateurs, rendant l'application plus réactive et moins lente.
- Latence perçue réduite : En affichant des résultats intermédiaires, les utilisateurs perçoivent le processus comme plus rapide, même si l'opération globale prend le même temps.
- Engagement accru : Maintient les utilisateurs engagés en fournissant des mises à jour en temps réel et en les empêchant d'abandonner le formulaire en raison de délais perçus.
- Augmentation des taux de conversion : Une expérience utilisateur plus fluide et plus réactive peut entraîner des taux de conversion plus élevés, en particulier pour les formulaires complexes.
Techniques Avancées
1. Utiliser `useOptimistic` pour des Mises à Jour d'UI Immédiates
Le hook useOptimistic
vous permet de mettre à jour l'interface utilisateur de manière optimiste avant la fin de la Server Action. Cela peut fournir un temps de réponse perçu encore plus rapide, car l'interface utilisateur reflète immédiatement le résultat attendu.
import { useOptimistic } from 'react';
function MyComponent() {
const [optimisticState, addOptimistic] = useOptimistic(
initialState,
(state, newUpdate) => {
// Return the new state based on the update
return { ...state, ...newUpdate };
}
);
const handleClick = async () => {
addOptimistic({ someValue: 'optimistic update' });
await myServerAction();
};
return (
<div>
<p>{optimisticState.someValue}</p>
<button onClick={handleClick}>Update</button>
</div>
);
}
Dans l'exemple du convertisseur de devises, vous pourriez mettre à jour de manière optimiste le montant converti en fonction du taux de change actuel, offrant un aperçu immédiat à l'utilisateur avant que le calcul réel ne se termine sur le serveur. Si le serveur renvoie une erreur, vous pouvez annuler la mise à jour optimiste.
2. Implémenter la Gestion des Erreurs et des Mécanismes de Repli
Il est crucial d'implémenter une gestion des erreurs robuste et des mécanismes de repli pour gérer les cas où la Server Action échoue ou la connexion réseau est interrompue. Vous pouvez utiliser le bloc try...catch
dans la Server Action pour attraper les erreurs et renvoyer un message d'erreur approprié au client.
// 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.' };
}
};
Côté client, vous pouvez afficher le message d'erreur à l'utilisateur et proposer des options pour réessayer l'opération ou contacter le support.
3. Mise en Cache des Taux de Change pour la Performance
La récupération des taux de change à partir d'une API externe peut être un goulot d'étranglement pour les performances. Pour améliorer les performances, vous pouvez mettre en cache les taux de change en utilisant un mécanisme de mise en cache comme Redis ou Memcached. Le unstable_cache
de Next.js (utilisé dans l'exemple) fournit une solution de mise en cache intégrée. N'oubliez pas d'invalider le cache périodiquement pour vous assurer que les taux de change sont à jour.
4. Considérations sur l'Internationalisation
Lors de la création d'applications pour un public mondial, il est important de prendre en compte l'internationalisation (i18n). Cela inclut :
- Formatage des nombres : Utilisez des formats de nombres appropriés pour différentes locales (par exemple, en utilisant des virgules ou des points comme séparateurs décimaux).
- Formatage des devises : Affichez les symboles et les formats de devise en fonction de la locale de l'utilisateur.
- Formatage de la date et de l'heure : Utilisez des formats de date et d'heure appropriés pour différentes locales.
- Localisation : Traduisez l'interface utilisateur dans différentes langues.
Des bibliothèques comme Intl
et react-intl
peuvent vous aider à implémenter l'i18n dans vos applications React.
Exemples et Cas d'Utilisation du Monde Réel
- E-commerce : Affichage des frais de port et des estimations de livraison en temps réel à mesure que l'utilisateur ajoute des articles à son panier.
- Applications financières : Fourniture de cotations boursières et de mises à jour de portefeuille en temps réel.
- Réservation de voyages : Affichage des prix et de la disponibilité des vols en temps réel.
- Visualisation de données : Streaming de mises à jour de données vers des graphiques et des diagrammes.
- Outils de collaboration : Affichage des mises à jour en temps réel des documents et des projets.
Conclusion
Le streaming de réponse des Server Actions de React offre un moyen puissant d'améliorer l'expérience utilisateur de vos applications React. En fournissant des réponses de formulaire progressives, vous pouvez créer des formulaires plus rapides, plus réactifs et plus engageants qui maintiennent les utilisateurs engagés et améliorent les taux de conversion. En combinant le streaming de réponse avec des techniques comme les mises à jour optimistes et la mise en cache, vous pouvez créer des expériences utilisateur vraiment exceptionnelles.
Alors que les Server Actions de React continuent d'évoluer, nous pouvons nous attendre à l'émergence de fonctionnalités et de capacités encore plus puissantes, simplifiant davantage le développement d'applications web complexes et dynamiques.
Exploration Supplémentaire
Ce guide fournit un aperçu complet du streaming de réponse des Server Actions de React et de son application aux réponses de formulaire progressives. En comprenant les concepts et les techniques abordés ici, vous pouvez tirer parti de cette fonctionnalité puissante pour créer des applications web plus rapides, plus réactives et plus engageantes.