La mise en cache des requêtes TanStack crée une expérience utilisateur instantanée. Combinée avec le composant KendoReact Loader, nous disposons d’une application React raffinée qui gère en douceur même les états de serveur complexes.
La récupération de données dans les applications React à grande échelle devient souvent un acte de jonglerie complexe. Nous devons gérer les états de chargement, gérer les erreurs, éviter les demandes en double et déterminer quand nos données mises en cache deviennent obsolètes. Sans une stratégie appropriée, nous nous retrouvons avec des composants pleins de utiliserEffet les hooks et les utilisateurs attendent que les mêmes données soient chargées à plusieurs reprises.
Requête TanStack (anciennement React Query) résout ces problèmes en traitant État du serveur en tant que citoyen de première classe dans les applications React. Son système de mise en cache intelligent est la sauce secrète qui permet de récupérer des données sans effort tout en offrant une expérience utilisateur rapide.
Dans cet article, nous explorerons le fonctionnement de la mise en cache de TanStack Query et le démontrerons avec des exemples pratiques utilisant le Progress Composant KendoReact Loader.
Le composant KendoReact Loader fait partie du KendoReact Gratuit suite, ce qui signifie que vous pouvez l’utiliser dans vos projets sans aucune exigence de licence ou d’enregistrement.
Requête TanStack
TanStack Query est une bibliothèque permettant de récupérer, de mettre en cache et de mettre à jour des données asynchrones dans React sans toucher à aucun état global. Il traite l’état du serveur comme une préoccupation distincte de l’état du client (comme les bascules de l’interface utilisateur ou les entrées de formulaire).
Avec TanStack Query, nous n’avons pas besoin de gérer nous-mêmes les états de chargement ou de mettre en cache les données manuellement. La bibliothèque gère cela pour nous en nous fournissant un ensemble de hooks simples qui fournissent des données, l’état de chargement et des informations sur les erreurs directement à nos composants.
Commençons par installer les packages nécessaires :
npm install @tanstack/react-query @progress/kendo-react-indicators
Chaque application TanStack Query a besoin d’un QueryClient et un QueryClientProvider pour gérer le cache et le fournir à notre arborescence de composants :
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import ProfileDemo from './ProfileDemo';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<ProfileDemo />
</QueryClientProvider>
);
}
export default App;
Cette configuration crée la base de toute notre magie de mise en cache. Le QueryClient gère le cache, tandis que le QueryClientProvider le rend disponible à tous les composants enfants.
Mise en cache de base en action
Voyons la mise en cache de TanStack Query en action avec un simple <UserProfile /> composant. Nous allons récupérer les données utilisateur du API JSONPlaceholder et utilisez le KendoReact Loader pour afficher les états de chargement.
import React from 'react';
import { useQuery } from '@tanstack/react-query';
import { Loader } from '@progress/kendo-react-indicators';
import { Button } from '@progress/kendo-react-buttons';
const fetchUser = async (userId) => {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
if (!response.ok) {
throw new Error('Failed to fetch user');
}
return response.json();
};
function UserProfile({ userId = 1 }) {
const query = useQuery({
queryKey: ['user', userId],
queryFn: () => fetchUser(userId),
});
if (query.isLoading) {
return (
<div className="loading-container">
<Loader size="large" type="infinite-spinner" />
<p>Loading user profile...</p>
</div>
);
}
if (query.error) {
return <div className="error">Error: {query.error.message}</div>;
}
return (
<div className="user-profile">
{query.isFetching && (
<div className="background-loading">
<Loader size="small" type="pulsing" />
<span>Updating...</span>
</div>
)}
<h2>{query.data.name}</h2>
<p>Email: {query.data.email}</p>
<p>Website: {query.data.website}</p>
<p>Company: {query.data.company.name}</p>
</div>
);
}
export function ProfileDemo() {
const [showProfile, setShowProfile] = React.useState(true);
return (
<div className="app">
<Button onClick={() => setShowProfile(!showProfile)}>
{showProfile ? 'Hide' : 'Show'} Profile
</Button>
{showProfile && <UserProfile />}
</div>
);
}
Voici ce qui se passe lorsque nous exécutons le code ci-dessus :
- Premier chargement: Le
isLoadingl’état esttruenous voyons donc la grande roulette pendant la récupération des données. - Les données arrivent: Le profil utilisateur s’affiche, et
isLoadingdevientfalse. - Basculer vers l’arrière et vers l’arrière: Cliquez à nouveau sur « Masquer le profil » puis sur « Afficher le profil ». Remarquez que le profil apparaît immédiatement! Pas de spinner de chargement cette fois.
- Mise à jour en arrière-plan: Nous pourrions voir un petit indicateur « Mise à jour… » car
query.isFetchingdevienttruecomme requête TanStack récupère en arrière-plan.
C’est la magie de la mise en cache. La deuxième fois que le composant est monté, TanStack Query sert immédiatement les données mises en cache tout en les mettant à jour silencieusement en arrière-plan !
Comprendre les clés de cache
Le clé de requête est crucial pour le fonctionnement de la mise en cache. Il s’agit d’un identifiant unique pour nos requêtes, et TanStack Query l’utilise pour stocker et récupérer les données mises en cache.
useQuery({ queryKey: ['user', 1], queryFn: () => fetchUser(1) });
useQuery({ queryKey: ['user', 1], queryFn: () => fetchUser(1) });
useQuery({ queryKey: ['user', 2], queryFn: () => fetchUser(2) });
Les clés de requête peuvent être de simples chaînes ou des tableaux avec plusieurs valeurs. L’utilisation de tableaux nous permet de créer des clés hiérarchiques qui rendent l’invalidation du cache plus puissante :
['user', userId]
['user', userId, 'posts']
['user', userId, 'profile']
Configuration du comportement du cache
Le comportement de mise en cache par défaut de TanStack Query est conçu pour être agressif mais raisonnable. Cependant, nous pouvons l’affiner en fonction des besoins de notre application en utilisant deux options clés : staleTime et gcTime.
Comprendre staleTime
Par défaut, staleTime est 0ce qui signifie que les données sont considérées comme « obsolètes » immédiatement après leur récupération. Les données obsolètes déclenchent des récupérations en arrière-plan lorsque :
- Le composant se remonte
- La fenêtre retrouve son focus
- Le réseau se reconnecte
Modifions notre existant UserProfile composant pour voir comment staleTime affecte le comportement :
function UserProfile({ userId = 1 }) {
const query = useQuery({
queryKey: ['user', userId],
queryFn: () => fetchUser(userId),
staleTime: 2 * 60 * 1000,
});
if (query.isLoading) {
return (
<div className="loading-container">
<Loader size="large" type="infinite-spinner" />
<p>Loading user profile...</p>
</div>
);
}
if (query.error) {
return <div className="error">Error: {query.error.message}</div>;
}
return (
<div className="user-profile">
{query.isFetching ? (
<div className="background-loading">
<Loader size="small" type="pulsing" />
<span>Updating...</span>
</div>
) : (
<div className="fresh-indicator">✨ Data is fresh!</div>
)}
<h2>{query.data.name}</h2>
<p>Email: {query.data.email}</p>
<p>Website: {query.data.website}</p>
<p>Company: {query.data.company.name}</p>
</div>
);
}
Ci-dessus, nous avons spécifié 2 minutes comme nouvelle valeur de temps obsolète. Avec 2 minutes staleTime:
- Les données apparaissent instantanément du cache lors du remontage.
- Pas de récupération en arrière-plan se produit pendant ces 2 minutes.
- Le message « ✨ Les données sont fraîches ! » L’indicateur indique lorsqu’aucune récupération n’a lieu.
- Après 2 minutes, la récupération en arrière-plan reprend.
Comprendre gcTime (Garbage Collection Time)
Le gcTime (anciennement cacheTime) détermine la durée pendant laquelle les données inactives mises en cache restent en mémoire. La valeur par défaut est de 5 minutes.
Pour voir cela en action avec notre ProfileDemoon peut modifier le UserProfile composant pour utiliser un gcTime:
function UserProfile({ userId = 1 }) {
const query = useQuery({
queryKey: ['user', userId],
queryFn: () => fetchUser(userId),
gcTime: 30 * 1000,
});
if (query.isLoading) {
return (
<div className="loading-container">
<Loader size="large" type="infinite-spinner" />
<p>Loading user profile...</p>
</div>
);
}
if (query.error) {
return <div className="error">Error: {query.error.message}</div>;
}
return (
<div className="user-profile">
<h2>{query.data.name}</h2>
<p>Email: {query.data.email}</p>
<p>Website: {query.data.website}</p>
<p>Company: {query.data.company.name}</p>
</div>
);
}
Avec 30 secondes gcTimesi nous utilisons le bouton « Masquer le profil » dans notre ProfileDemo et attendez plus de 30 secondes avant de cliquer à nouveau sur « Afficher le profil », nous verrons la flèche de chargement car le cache a été récupéré.
Comparaison des scénarios de mise en cache
Améliorons notre ProfileDemo pour créer une comparaison de différentes stratégies de mise en cache :
import React from 'react';
import { useQuery } from '@tanstack/react-query';
import { Loader } from '@progress/kendo-react-indicators';
import { Button } from '@progress/kendo-react-buttons';
function UserProfile({ userId = 1, title = "User Profile", cacheConfig = {} }) {
const query = useQuery({
queryKey: ['user', userId, title],
queryFn: () => fetchUser(userId),
...cacheConfig,
});
if (query.isLoading) {
return (
<div className="profile-loading">
<Loader size="medium" type="infinite-spinner" />
<p>Loading {title}...</p>
</div>
);
}
if (query.error) {
return <div className="error">Error: {query.error.message}</div>;
}
return (
<div className="user-profile">
<h3>{title}</h3>
{query.isFetching ? (
<div className="background-loading">
<Loader size="small" type="pulsing" />
<span>Updating...</span>
</div>
) : (
<div className="status-indicator">Ready</div>
)}
<h4>{query.data.name}</h4>
<p>Email: {query.data.email}</p>
<p>Company: {query.data.company.name}</p>
</div>
);
}
export function ProfileDemo() {
const [showProfiles, setShowProfiles] = React.useState(true);
return (
<div className="comparison-container">
<Button onClick={() => setShowProfiles(!showProfiles)}>
{showProfiles ? 'Hide' : 'Show'} All Profiles
</Button>
{showProfiles && (
<div className="profiles-grid">
<UserProfile
title="Default Caching"
cacheConfig={{}}
/>
<UserProfile
title="With StaleTime (1 min)"
cacheConfig={{ staleTime: 60 * 1000 }}
/>
<UserProfile
title="No Cache (gcTime: 0)"
cacheConfig={{ gcTime: 0 }}
/>
</div>
)}
</div>
);
}
Maintenant notre amélioré ProfileDemo montre trois stratégies de mise en cache différentes utilisant les mêmes données utilisateur :
- Mise en cache par défaut: Affichage instantané avec récupération en arrière-plan (nous verrons brièvement « Mise à jour… »)
- Avec StaleTime (1 min): Affichage instantané, pas de récupération pendant 1 minute (affiche l’état « Prêt »)
- Pas de cache: Affiche toujours le spinner de chargement lorsqu’il est activé, car les données sont immédiatement récupérées
Configuration avancée du cache
Pour des scénarios plus complexes, nous pouvons configurer des comportements de mise en cache supplémentaires :
function AdvancedCacheExample() {
const query = useQuery({
queryKey: ['advanced-cache-example'],
queryFn: fetchUser,
staleTime: 5 * 60 * 1000,
gcTime: 10 * 60 * 1000,
refetchOnMount: true,
refetchOnWindowFocus: false,
refetchOnReconnect: true,
retry: 3,
retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 30000),
});
}
Ces options supplémentaires, comme refetchOnMount, refetchOnWindowFocus et retrydonnez-nous un contrôle granulaire sur le moment et la manière dont nos données sont récupérées et mises en cache.
Configuration du cache global
Nous pouvons définir globalement le comportement du cache par défaut lors de la création de notre QueryClient:
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 2 * 60 * 1000,
gcTime: 10 * 60 * 1000,
refetchOnWindowFocus: false,
},
},
});
Cette approche nous permet de définir des valeurs par défaut raisonnables pour l’ensemble de notre application tout en autorisant les remplacements par requête en cas de besoin.
Conclure
Le système de mise en cache de TanStack Query transforme la façon dont nous gérons l’état du serveur dans les applications React. Gérer intelligemment quand afficher les données mises en cache et quand récupérer de nouvelles données crée une expérience utilisateur réactive qui semble instantanée tout en gardant les informations à jour.
En combinaison avec des indicateurs de chargement tels que le composant KendoReact Loader, nous pouvons créer des applications professionnelles qui gèrent avec élégance les complexités de l’état du serveur.
Pour plus d’informations, n’oubliez pas de consulter la documentation officielle :
N’oubliez pas : le KendoReact Loader est gratuit, même en production.
Source link
