4.5 KiB
4.5 KiB
| name | description |
|---|---|
| type-safe-data-fetching | Architect resilient, type-safe asynchronous data fetching pipelines with TanStack Query v5, Server Actions, request deduplication, background revalidation, AbortController cancellation, and optimistic mutations. |
Type-Safe Data Fetching & Network Resilience (TanStack Query v5)
Ce skill bannit les anti-patterns classiques de récupération de données (cascades de useEffect, requêtes orphelines sans AbortController, données désynchronisées au retour sur l'onglet). Il impose l'utilisation de TanStack Query v5 (React Query) ou de Server Actions typées de bout en bout.
🎯 Déclencheurs d'Activation
Activez ce skill dès que :
- Vous consommez des API REST, GraphQL ou des bases de données distantes dans une interface web.
- Vous devez mettre en cache, synchroniser et dédoublonner des requêtes réseau asynchrones.
- Vous implémentez une mutation avec mise à jour optimiste et annulation (rollback) en cas d'échec.
- Vous gérez le rafraîchissement des données lors du retour du focus sur la fenêtre (
refetchOnWindowFocus). - Vous devez annuler des requêtes réseau lors du démontage d'un composant via
AbortSignal.
🚫 1. Anti-Pattern Interdit : useEffect + fetch
// ❌ INTERDIT : Entraîne des waterfalls, des race conditions et aucun cache
useEffect(() => {
fetch('/api/projects')
.then(res => res.json())
.then(data => setProjects(data));
}, []);
✅ La Norme Moderne : Query Hooks Déclaratifs avec TanStack Query v5
import { useQuery } from '@tanstack/react-query';
interface Project {
id: string;
title: string;
status: 'active' | 'archived';
}
export function useProjects() {
return useQuery<Project[]>({
queryKey: ['projects'],
queryFn: async ({ signal }) => {
// 1. Passage obligatoire du signal d'annulation (AbortController)
const res = await fetch('/api/projects', { signal });
if (!res.ok) throw new Error('Échec du chargement des projets');
return res.json();
},
// 2. Stratégie de fraîcheur : les données sont fraîches pendant 2 minutes
staleTime: 1000 * 60 * 2,
// 3. Revalidation intelligente au focus de la fenêtre
refetchOnWindowFocus: true,
});
}
⚡ 2. Mutations avec Mise à Jour Optimiste (Instant UI + Rollback)
Ne faites jamais attendre l'utilisateur pendant une requête POST ou PATCH. Mettez à jour l'interface instantanément tout en conservant un instantané pour restaurer l'état en cas d'erreur réseau :
import { useMutation, useQueryClient } from '@tanstack/react-query';
export function useToggleProjectStatus() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({ id, status }: { id: string; status: 'active' | 'archived' }) => {
const res = await fetch(`/api/projects/${id}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ status }),
});
if (!res.ok) throw new Error('Erreur lors de la modification');
return res.json();
},
// 1. Avant la requête : mise à jour optimiste du cache
onMutate: async (updatedProject) => {
await queryClient.cancelQueries({ queryKey: ['projects'] });
const previousProjects = queryClient.getQueryData<Project[]>(['projects']);
queryClient.setQueryData<Project[]>(['projects'], (old = []) =>
old.map((p) => (p.id === updatedProject.id ? { ...p, status: updatedProject.status } : p))
);
return { previousProjects };
},
// 2. En cas d'échec : restauration immédiate de l'état antérieur
onError: (err, newTodo, context) => {
if (context?.previousProjects) {
queryClient.setQueryData(['projects'], context.previousProjects);
}
},
// 3. Après résolution : synchronisation avec les données serveur réelles
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['projects'] });
},
});
}
📋 Checklist de Conformité Data Fetching
- Aucun appel réseau manuel non mis en cache dans un
useEffectnu. - Le paramètre
{ signal }est passé àfetch()pour annuler les requêtes orphelines. - Une valeur explicite de
staleTimeest configurée pour éviter le sur-requêtage intempestif. - Les mutations à fort impact visuel (likes, toggles, ajouts rapides) implémentent une mise à jour optimiste avec rollback.
- Les erreurs d'API sont typées et interceptées pour être traitées par des Error Boundaries ou des Toasts.