Récupération de données obsolètes pendant la revalidation avec React Hooks : un guide
Publié: 2022-03-11Tirer parti de l'extension HTTP Cache-Control
stale-while-revalidate est une technique populaire. Cela implique d'utiliser des actifs mis en cache (périmés) s'ils sont trouvés dans le cache, puis de revalider le cache et de le mettre à jour avec une version plus récente de l'actif si nécessaire. D'où le nom stale-while-revalidate
.
Comment fonctionne stale-while-revalidate
Lorsqu'une requête est envoyée pour la première fois, elle est mise en cache par le navigateur. Ensuite, lorsque la même requête est envoyée une deuxième fois, le cache est d'abord vérifié. Si le cache de cette demande est disponible et valide, le cache est renvoyé comme réponse. Ensuite, le cache est vérifié pour l'obsolescence et est mis à jour s'il est obsolète. L'obsolescence d'un cache est déterminée par la valeur max-age
présente dans l'en-tête Cache-Control
avec stale-while-revalidate
.
Cela permet des chargements de page rapides, car les actifs mis en cache ne se trouvent plus dans le chemin critique. Ils sont chargés instantanément. De plus, comme les développeurs contrôlent la fréquence d'utilisation et de mise à jour du cache, ils peuvent empêcher les navigateurs d'afficher des données trop obsolètes aux utilisateurs.
Les lecteurs pourraient penser que, s'ils peuvent faire en sorte que le serveur utilise certains en-têtes dans ses réponses et laisse le navigateur le faire à partir de là, alors à quoi bon utiliser React et Hooks pour la mise en cache ?
Il s'avère que l'approche serveur et navigateur ne fonctionne bien que lorsque nous voulons mettre en cache du contenu statique. Qu'en est-il de l'utilisation de stale-while-revalidate
pour une API dynamique ? Il est difficile de trouver de bonnes valeurs pour max-age
et stale-while-revalidate
dans ce cas. Souvent, invalider le cache et récupérer une nouvelle réponse à chaque fois qu'une requête est envoyée sera la meilleure option. Cela signifie effectivement aucune mise en cache du tout. Mais avec React et Hooks, nous pouvons faire mieux.
stale-while-revalidate
pour l'API
Nous avons remarqué que le stale-while-revalidate
de HTTP ne fonctionne pas bien avec les requêtes dynamiques comme les appels d'API.
Même si nous finissons par l'utiliser, le navigateur renverra soit le cache, soit la nouvelle réponse, pas les deux. Cela ne va pas bien avec une requête API car nous aimerions recevoir de nouvelles réponses à chaque fois qu'une requête est envoyée. Cependant, attendre de nouvelles réponses retarde l'utilisation significative de l'application.
Alors que faisons-nous?
Nous implémentons un mécanisme de mise en cache personnalisé. Dans ce cadre, nous trouvons un moyen de renvoyer à la fois le cache et la nouvelle réponse. Dans l'interface utilisateur, la réponse mise en cache est remplacée par une nouvelle réponse lorsqu'elle est disponible. Voici à quoi ressemblerait la logique :
- Lorsqu'une demande est envoyée au point de terminaison du serveur d'API pour la première fois, mettez la réponse en cache, puis renvoyez-la.
- La prochaine fois que la même demande d'API se produira, utilisez immédiatement la réponse mise en cache.
- Ensuite, envoyez la requête de manière asynchrone pour récupérer une nouvelle réponse. Lorsque la réponse arrive, propagez de manière asynchrone les modifications apportées à l'interface utilisateur et mettez à jour le cache.
Cette approche permet des mises à jour instantanées de l'interface utilisateur, car chaque demande d'API est mise en cache, mais également une éventuelle exactitude de l'interface utilisateur, car les nouvelles données de réponse sont affichées dès qu'elles sont disponibles.
Dans ce tutoriel, nous verrons une approche étape par étape sur la façon de mettre cela en œuvre. Nous appellerons cette approche obsolète pendant l'actualisation puisque l'interface utilisateur est en fait actualisée lorsqu'elle reçoit la nouvelle réponse.
Préparatifs : l'API
Pour lancer ce didacticiel, nous aurons d'abord besoin d'une API à partir de laquelle nous récupérons les données. Heureusement, il existe une tonne de faux services d'API disponibles. Pour ce tutoriel, nous utiliserons reqres.in.
Les données que nous récupérons sont une liste d'utilisateurs avec un paramètre de requête de page
. Voici à quoi ressemble le code de récupération :
fetch("https://reqres.in/api/users?page=2") .then(res => res.json()) .then(json => { console.log(json); });
L'exécution de ce code nous donne la sortie suivante. En voici une version non répétitive :
{ page: 2, per_page: 6, total: 12, total_pages: 2, data: [ { id: 7, email: "[email protected]", first_name: "Michael", last_name: "Lawson", avatar: "https://s3.amazonaws.com/uifaces/faces/twitter/follettkyle/128.jpg" }, // 5 more items ] }
Vous pouvez voir que c'est comme une vraie API. Nous avons la pagination dans la réponse. Le paramètre de requête de page
est responsable du changement de page, et nous avons un total de deux pages dans l'ensemble de données.
Utilisation de l'API dans une application React
Voyons comment nous utilisons l'API dans une application React. Une fois que nous saurons comment le faire, nous découvrirons la partie mise en cache. Nous allons utiliser une classe pour créer notre composant. Voici le code :
import React from "react"; import PropTypes from "prop-types"; export default class Component extends React.Component { state = { users: [] }; componentDidMount() { this.load(); } load() { fetch(`https://reqres.in/api/users?page=${this.props.page}`) .then(res => res.json()) .then(json => { this.setState({ users: json.data }); }); } componentDidUpdate(prevProps) { if (prevProps.page !== this.props.page) { this.load(); } } render() { const users = this.state.users.map(user => ( <p key={user.id}> <img src={user.avatar} alt={user.first_name} style={{ height: 24, width: 24 }} /> {user.first_name} {user.last_name} </p> )); return <div>{users}</div>; } } Component.propTypes = { page: PropTypes.number.isRequired };
Notez que nous obtenons la valeur de la page
via props
, comme cela se produit souvent dans les applications du monde réel. De plus, nous avons une fonction componentDidUpdate
, qui récupère les données de l'API à chaque fois this.props.page
change.
À ce stade, une liste de six utilisateurs s'affiche, car l'API renvoie six éléments par page :
Ajout de la mise en cache obsolète pendant l'actualisation
Si nous voulons ajouter une mise en cache obsolète pendant l'actualisation, nous devons mettre à jour notre logique d'application pour :
- Mettez en cache la réponse d'une requête de manière unique après sa première récupération.
- Renvoie instantanément la réponse mise en cache si le cache d'une requête est trouvé. Ensuite, envoyez la demande et renvoyez la nouvelle réponse de manière asynchrone. Mettez également cette réponse en cache pour la prochaine fois.
Nous pouvons le faire en ayant un objet CACHE
global qui stocke le cache de manière unique. Pour l'unicité, nous pouvons utiliser la valeur this.props.page
comme clé dans notre objet CACHE
. Ensuite, nous codons simplement l'algorithme mentionné ci-dessus.
import apiFetch from "./apiFetch"; const CACHE = {}; export default class Component extends React.Component { state = { users: [] }; componentDidMount() { this.load(); } load() { if (CACHE[this.props.page] !== undefined) { this.setState({ users: CACHE[this.props.page] }); } apiFetch(`https://reqres.in/api/users?page=${this.props.page}`).then( json => { CACHE[this.props.page] = json.data; this.setState({ users: json.data }); } ); } componentDidUpdate(prevProps) { if (prevProps.page !== this.props.page) { this.load(); } } render() { // same render code as above } }
Étant donné que le cache est renvoyé dès qu'il est trouvé et que les nouvelles données de réponse sont également renvoyées par setState
, cela signifie que nous avons des mises à jour transparentes de l'interface utilisateur et plus de temps d'attente sur l'application à partir de la deuxième demande. C'est parfait, et c'est la méthode du rafraîchissement en cours d'actualisation en un mot.
La fonction apiFetch
ici n'est rien d'autre qu'un wrapper sur la fetch
afin que nous puissions voir l'avantage de la mise en cache en temps réel. Pour ce faire, il ajoute un utilisateur aléatoire à la liste des users
renvoyée par la requête API. Il y ajoute également un délai aléatoire :
export default async function apiFetch(...args) { await delay(Math.ceil(400 + Math.random() * 300)); const res = await fetch(...args); const json = await res.json(); json.data.push(getFakeUser()); return json; } function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
La fonction getFakeUser()
ici est responsable de la création d'un faux objet utilisateur.
Avec ces changements, notre API est plus réelle qu'avant.
- Il a un retard aléatoire dans la réponse.
- Il renvoie des données légèrement différentes pour les mêmes requêtes.
Compte tenu de cela, lorsque nous modifions le prop de page
transmis au Component
à partir de notre composant principal, nous pouvons voir la mise en cache de l'API en action. Essayez de cliquer sur le bouton Basculer une fois toutes les quelques secondes dans ce CodeSandbox et vous devriez voir un comportement comme celui-ci :
Si vous regardez attentivement, certaines choses se produisent.
- Lorsque l'application démarre et est dans son état par défaut, nous voyons une liste de sept utilisateurs. Prenez note du dernier utilisateur de la liste puisque c'est l'utilisateur qui sera modifié aléatoirement la prochaine fois que cette requête sera envoyée.
- Lorsque nous cliquons sur Basculer pour la première fois, il attend un peu de temps (400-700 ms) puis met à jour la liste à la page suivante.
- Maintenant, nous sommes sur la deuxième page. Encore une fois, notez le dernier utilisateur de la liste.
- Maintenant, nous cliquons à nouveau sur Basculer et l'application reviendra à la première page. Notez que maintenant la dernière entrée est toujours le même utilisateur que nous avons noté à l'étape 1, puis il change plus tard pour le nouvel utilisateur (aléatoire). En effet, au départ, le cache était affiché, puis la réponse réelle a été déclenchée.
- Nous cliquons à nouveau sur Basculer. Le même phénomène se produit. La réponse mise en cache de la dernière fois est chargée instantanément, puis de nouvelles données sont récupérées, et nous voyons donc la dernière mise à jour d'entrée à partir de ce que nous avons noté à l'étape 3.
Ça y est, la mise en cache obsolète pendant l'actualisation que nous recherchions. Mais cette approche souffre d'un problème de duplication de code. Voyons comment cela se passe si nous avons un autre composant de récupération de données avec mise en cache. Ce composant affiche les éléments différemment de notre premier composant.
Ajout de Stale-while-refresh à un autre composant
Nous pouvons le faire en copiant simplement la logique du premier composant. Notre deuxième composant affiche une liste de chats :
const CACHE = {}; export default class Component2 extends React.Component { state = { cats: [] }; componentDidMount() { this.load(); } load() { if (CACHE[this.props.page] !== undefined) { this.setState({ cats: CACHE[this.props.page] }); } apiFetch(`https://reqres.in/api/cats?page=${this.props.page}`).then( json => { CACHE[this.props.page] = json.data; this.setState({ cats: json.data }); } ); } componentDidUpdate(prevProps) { if (prevProps.page !== this.props.page) { this.load(); } } render() { const cats = this.state.cats.map(cat => ( <p key={cat.id} style={{ background: cat.color, padding: "4px", width: 240 }} > {cat.name} (born {cat.year}) </p> )); return <div>{cats}</div>; } }
Comme vous pouvez le voir, la logique de composant impliquée ici est à peu près la même que celle du premier composant. La seule différence réside dans le point de terminaison demandé et le fait qu'il affiche les éléments de la liste différemment.
Maintenant, nous montrons ces deux composants côte à côte. Vous pouvez voir qu'ils se comportent de la même manière :
Pour arriver à ce résultat, nous avons dû faire beaucoup de duplication de code. Si nous avions plusieurs composants comme celui-ci, nous dupliquerions trop de code.
Pour le résoudre de manière non dupliquée, nous pouvons avoir un composant d'ordre supérieur pour récupérer et mettre en cache les données et les transmettre en tant qu'accessoires. Ce n'est pas l'idéal mais ça marchera. Mais si nous devions faire plusieurs requêtes dans un seul composant, avoir plusieurs composants d'ordre supérieur deviendrait moche très rapidement.
Ensuite, nous avons le modèle d'accessoires de rendu, qui est probablement la meilleure façon de le faire dans les composants de classe. Cela fonctionne parfaitement, mais encore une fois, il est sujet à "l'enfer de l'emballage" et nous oblige parfois à lier le contexte actuel. Ce n'est pas une excellente expérience de développement et peut entraîner de la frustration et des bogues.

C'est là que React Hooks sauve la mise. Ils nous permettent de placer la logique des composants dans un conteneur réutilisable afin que nous puissions l'utiliser à plusieurs endroits. Les React Hooks ont été introduits dans React 16.8 et ils ne fonctionnent qu'avec des composants fonctionnels. Avant d'aborder le contrôle du cache React, en particulier la mise en cache du contenu avec des crochets, voyons d'abord comment nous effectuons une simple récupération de données dans les composants de fonction.
Récupération de données d'API dans les composants de fonction
Pour récupérer les données de l'API dans les composants de fonction, nous utilisons les crochets useState
et useEffect
.
useState
est analogue à state
et setState
des composants de classe. Nous utilisons ce crochet pour avoir des conteneurs atomiques d'état à l'intérieur d'un composant de fonction.
useEffect
est un hook de cycle de vie, et vous pouvez le considérer comme une combinaison de componentDidMount
, componentDidUpdate
et componentWillUnmount
. Le deuxième paramètre passé à useEffect
est appelé un tableau de dépendances. Lorsque le tableau de dépendances change, le rappel passé en premier argument à useEffect
est exécuté à nouveau.
Voici comment nous utiliserons ces crochets pour implémenter la récupération de données :
import React, { useState, useEffect } from "react"; export default function Component({ page }) { const [users, setUsers] = useState([]); useEffect(() => { fetch(`https://reqres.in/api/users?page=${page}`) .then(res => res.json()) .then(json => { setUsers(json.data); }); }, [page]); const usersDOM = users.map(user => ( <p key={user.id}> <img src={user.avatar} alt={user.first_name} style={{ height: 24, width: 24 }} /> {user.first_name} {user.last_name} </p> )); return <div>{usersDOM}</div>; }
En spécifiant la page
comme dépendance à useEffect
, nous demandons à React d'exécuter notre rappel useEffect à chaque fois que page
est modifiée. C'est comme componentDidUpdate
. En outre, useEffect
s'exécute toujours la première fois, il fonctionne donc également comme componentDidMount
.
Stale-while-refresh dans les composants de fonction
Nous savons que useEffect
est similaire aux méthodes de cycle de vie des composants. Nous pouvons donc modifier la fonction de rappel qui lui est transmise pour créer la mise en cache obsolète pendant l'actualisation que nous avions dans les composants de classe. Tout reste le même sauf le crochet useEffect
.
const CACHE = {}; export default function Component({ page }) { const [users, setUsers] = useState([]); useEffect(() => { if (CACHE[page] !== undefined) { setUsers(CACHE[page]); } apiFetch(`https://reqres.in/api/users?page=${page}`).then(json => { CACHE[page] = json.data; setUsers(json.data); }); }, [page]); // ... create usersDOM from users return <div>{usersDOM}</div>; }
Ainsi, nous avons une mise en cache obsolète pendant l'actualisation fonctionnant dans un composant de fonction.
Nous pouvons faire de même pour le deuxième composant, c'est-à-dire le convertir en fonction et implémenter la mise en cache obsolète pendant l'actualisation. Le résultat sera identique à ce que nous avions en classe.
Mais ce n'est pas mieux que les composants de classe, n'est-ce pas ? Voyons donc comment nous pouvons utiliser la puissance d'un crochet personnalisé pour créer une logique modulaire d'obsolescence pendant l'actualisation que nous pouvons utiliser sur plusieurs composants.
Un hook personnalisé en cours de rafraîchissement
Tout d'abord, affinons la logique que nous voulons déplacer dans un crochet personnalisé. Si vous regardez le code précédent, vous savez que c'est la partie useState
et useEffect
. Plus précisément, c'est la logique que nous voulons modulariser.
const [users, setUsers] = useState([]); useEffect(() => { if (CACHE[page] !== undefined) { setUsers(CACHE[page]); } apiFetch(`https://reqres.in/api/users?page=${page}`).then(json => { CACHE[page] = json.data; setUsers(json.data); }); }, [page]);
Puisque nous devons le rendre générique, nous devrons rendre l'URL dynamique. Nous avons donc besoin d'avoir l' url
comme argument. Nous devrons également mettre à jour la logique de mise en cache, car plusieurs requêtes peuvent avoir la même valeur page
. Heureusement, lorsque page
est incluse avec l'URL du point de terminaison, elle donne une valeur unique pour chaque requête unique. Nous pouvons donc simplement utiliser l'URL entière comme clé pour la mise en cache :
const [data, setData] = useState([]); useEffect(() => { if (CACHE[url] !== undefined) { setData(CACHE[url]); } apiFetch(url).then(json => { CACHE[url] = json.data; setData(json.data); }); }, [url]);
C'est à peu près tout. Après l'avoir enveloppé dans une fonction, nous aurons notre crochet personnalisé. Jetez un oeil ci-dessous.
const CACHE = {}; export default function useStaleRefresh(url, defaultValue = []) { const [data, setData] = useState(defaultValue); useEffect(() => { // cacheID is how a cache is identified against a unique request const cacheID = url; // look in cache and set response if present if (CACHE[cacheID] !== undefined) { setData(CACHE[cacheID]); } // fetch new data apiFetch(url).then(newData => { CACHE[cacheID] = newData.data; setData(newData.data); }); }, [url]); return data; }
Notez que nous y avons ajouté un autre argument appelé defaultValue
. La valeur par défaut d'un appel d'API peut être différente si vous utilisez ce hook dans plusieurs composants. C'est pourquoi nous l'avons rendu personnalisable.
La même chose peut être faite pour la clé de data
dans l'objet newData
. Si votre crochet personnalisé renvoie une variété de données, vous voudrez peut-être simplement renvoyer newData
et non newData.data
et gérer cette traversée côté composant.
Maintenant que nous avons notre crochet personnalisé, qui fait le gros du travail de mise en cache obsolète pendant l'actualisation, voici comment nous le connectons à nos composants. Remarquez la quantité de code que nous avons pu réduire. Notre composant entier est maintenant composé de trois déclarations. C'est une grande victoire.
import useStaleRefresh from "./useStaleRefresh"; export default function Component({ page }) { const users = useStaleRefresh(`https://reqres.in/api/users?page=${page}`, []); const usersDOM = users.map(user => ( <p key={user.id}> <img src={user.avatar} alt={user.first_name} style={{ height: 24, width: 24 }} /> {user.first_name} {user.last_name} </p> )); return <div>{usersDOM}</div>; }
Nous pouvons faire la même chose pour le deuxième composant. Il ressemblera à ceci:
export default function Component2({ page }) { const cats = useStaleRefresh(`https://reqres.in/api/cats?page=${page}`, []); // ... create catsDOM from cats return <div>{catsDOM}</div>; }
Il est facile de voir combien de code passe-partout nous pouvons économiser si nous utilisons ce crochet. Le code semble mieux aussi. Si vous voulez voir toute l'application en action, rendez-vous sur ce CodeSandbox.
Ajout d'un indicateur de chargement à useStaleRefresh
Maintenant que nous avons les bases sur le point, nous pouvons ajouter plus de fonctionnalités à notre crochet personnalisé. Par exemple, nous pouvons ajouter une valeur isLoading
dans le crochet qui est vraie chaque fois qu'une requête unique est envoyée et nous n'avons pas de cache à afficher entre-temps.
Nous faisons cela en ayant un état séparé pour isLoading
et en le définissant en fonction de l'état du crochet. Autrement dit, lorsqu'aucun contenu Web mis en cache n'est disponible, nous le définissons sur true
, sinon nous le définissons sur false
.
Voici le crochet mis à jour :
export default function useStaleRefresh(url, defaultValue = []) { const [data, setData] = useState(defaultValue); const [isLoading, setLoading] = useState(true); useEffect(() => { // cacheID is how a cache is identified against a unique request const cacheID = url; // look in cache and set response if present if (CACHE[cacheID] !== undefined) { setData(CACHE[cacheID]); setLoading(false); } else { // else make sure loading set to true setLoading(true); } // fetch new data apiFetch(url).then(newData => { CACHE[cacheID] = newData.data; setData(newData.data); setLoading(false); }); }, [url]); return [data, isLoading]; }
Nous pouvons maintenant utiliser la nouvelle valeur isLoading
dans nos composants.
export default function Component({ page }) { const [users, isLoading] = useStaleRefresh( `https://reqres.in/api/users?page=${page}`, [] ); if (isLoading) { return <div>Loading</div>; } // ... create usersDOM from users return <div>{usersDOM}</div>; }
Notez qu'une fois cela fait, vous voyez le texte "Chargement" lorsqu'une demande unique est envoyée pour la première fois et qu'aucun cache n'est présent.
Utilisation de la prise en charge de useStaleRefresh
Toute fonction async
Nous pouvons rendre notre crochet personnalisé encore plus puissant en le faisant prendre en charge n'importe quelle fonction async
plutôt que simplement les requêtes réseau GET
. L'idée de base derrière cela restera la même.
- Dans le crochet, vous appelez une fonction asynchrone qui renvoie une valeur après un certain temps.
- Chaque appel unique à une fonction asynchrone est correctement mis en cache.
Une simple concaténation de function.name
et d' arguments
fonctionnera comme une clé de cache pour notre cas d'utilisation. En utilisant cela, voici à quoi ressemblera notre crochet :
import { useState, useEffect, useRef } from "react"; import isEqual from "lodash/isEqual"; const CACHE = {}; export default function useStaleRefresh(fn, args, defaultValue = []) { const prevArgs = useRef(null); const [data, setData] = useState(defaultValue); const [isLoading, setLoading] = useState(true); useEffect(() => { // args is an object so deep compare to rule out false changes if (isEqual(args, prevArgs.current)) { return; } // cacheID is how a cache is identified against a unique request const cacheID = hashArgs(fn.name, ...args); // look in cache and set response if present if (CACHE[cacheID] !== undefined) { setData(CACHE[cacheID]); setLoading(false); } else { // else make sure loading set to true setLoading(true); } // fetch new data fn(...args).then(newData => { CACHE[cacheID] = newData; setData(newData); setLoading(false); }); }, [args, fn]); useEffect(() => { prevArgs.current = args; }); return [data, isLoading]; } function hashArgs(...args) { return args.reduce((acc, arg) => stringify(arg) + ":" + acc, ""); } function stringify(val) { return typeof val === "object" ? JSON.stringify(val) : String(val); }
Comme vous pouvez le voir, nous utilisons une combinaison de nom de fonction et de ses arguments stringifiés pour identifier de manière unique un appel de fonction et ainsi le mettre en cache. Cela fonctionne pour notre application simple, mais cet algorithme est sujet aux collisions et aux comparaisons lentes. (Avec des arguments non sérialisables, cela ne fonctionnera pas du tout.) Ainsi, pour les applications du monde réel, un algorithme de hachage approprié est plus approprié.
Une autre chose à noter ici est l'utilisation de useRef
. useRef
est utilisé pour conserver les données tout au long du cycle de vie du composant englobant. Étant donné que args
est un tableau, qui est un objet en JavaScript, chaque nouveau rendu du composant à l'aide du crochet entraîne la modification du pointeur de référence args
. Mais args
fait partie de la liste des dépendances dans notre premier useEffect
. Ainsi, le changement d' useEffect
args
si rien n'a changé. Pour contrer cela, nous effectuons une comparaison approfondie entre les arguments anciens et actuels en utilisant args
et ne laissons le rappel useEffect
s'exécuter que si les args
ont réellement changé.
Maintenant, nous pouvons utiliser ce nouveau crochet useStaleRefresh
comme suit. Notez le changement de defaultValue
ici. Puisqu'il s'agit d'un crochet à usage général, nous ne comptons pas sur notre crochet pour renvoyer la clé de data
dans l'objet de réponse.
export default function Component({ page }) { const [users, isLoading] = useStaleRefresh( apiFetch, [`https://reqres.in/api/users?page=${page}`], { data: [] } ); if (isLoading) { return <div>Loading</div>; } const usersDOM = users.data.map(user => ( <p key={user.id}> <img src={user.avatar} alt={user.first_name} style={{ height: 24, width: 24 }} /> {user.first_name} {user.last_name} </p> )); return <div>{usersDOM}</div>; }
Vous pouvez trouver le code entier dans ce CodeSandbox.
Ne faites pas attendre les utilisateurs : utilisez efficacement le contenu du cache avec les hooks Stale-while-refresh et React
Le crochet useStaleRefresh
que nous avons créé dans cet article est une preuve de concept qui montre ce qui est possible avec React Hooks. Essayez de jouer avec le code et voyez si vous pouvez l'intégrer à votre application.
Alternativement, vous pouvez également essayer de tirer parti de stale-while-refresh via une bibliothèque open source populaire et bien entretenue comme swr ou react-query. Les deux sont des bibliothèques puissantes et prennent en charge une multitude de fonctionnalités qui facilitent les demandes d'API.
React Hooks change la donne. Ils nous permettent de partager la logique des composants avec élégance. Cela n'était pas possible auparavant car l'état des composants, les méthodes de cycle de vie et le rendu étaient tous regroupés dans une seule entité : les composants de classe. Maintenant, nous pouvons avoir différents modules pour chacun d'eux. C'est idéal pour la composabilité et l'écriture d'un meilleur code. J'utilise des composants de fonction et des crochets pour tout le nouveau code React que j'écris, et je le recommande vivement à tous les développeurs React.