Réagir le rendu inutile de l'élément
Je viens de commencer à apprendre React et j'étais en train de créer une petite application qui appelle une API de devis. L'API a un point de terminaison qui renvoie une citation aléatoire. Lorsque l'application se charge initialement, elle appelle l'API et affiche un devis, et il y a un bouton sur lequel il est possible de cliquer pour obtenir un nouveau devis aléatoire (nouvel appel à l'API).
J'ai un composant racine nommé App. Ce composant a un composant QuoteWrap en tant qu'enfant. Le composant QuoteWrap a deux enfants: le bouton qui est utilisé pour obtenir un nouveau devis aléatoire et un composant Quote qui montre l'auteur du devis et le devis lui-même. Voici le code à l'intérieur du composant QuoteWrap:
export default function QuoteWrap() {
const { quoteData, isLoading, fireNewCall } = useQuote();
const handleClick = () => {
fireNewCall();
};
return(
<>
<button onClick={handleClick}>Get random quote</button>
{ isLoading ?
<h2>Loading...</h2>
:
<Quote author={quoteData.author} quote={quoteData.quote} />
}
</>
);
}
useQuote () est un hook personnalisé qui gère les appels à l'API et renvoie 3 valeurs: 1- les données, 2- si un appel est en cours et 3- une fonction pour faire un appel à l'API.
De toute évidence, chaque fois que vous cliquez sur le bouton, l'ensemble du composant QuoteWrap est re-rendu (comme quoteData et isLoading changent). Mais vraiment, le bouton n'a pas besoin d'être restitué car il ne change jamais.
Alors j'ai pensé: ok, je peux déplacer le bouton vers le composant App. Mais alors je n'ai pas accès à la fonction fireNewCall dans le hook useQuote.
Comment puis-je empêcher le rendu du bouton? Est-ce même important dans ce cas ou suis-je trop obsédé par les rediffusions React?
Merci!
Réponses
Votre composant sera rendu à chaque fois que la fonction handleClick change, c'est-à-dire à chaque fois que QuoteWrap est rendu.
La solution est le hook useCallback. useCallback retournera la même fonction à handleClick, chaque fois que QuoteWrap est rendu, tant que les dépendances n'ont pas changé.
https://reactjs.org/docs/hooks-reference.html#usecallback
Vous l'utiliseriez comme ceci:
const handleClick = useCallback(() => {
fireNewCall();
},[fireNewCall]);
fireNewCall est la dépendance, donc tant que useQuote renvoie une fonction fireNewCall stable, votre bouton ne sera pas rendu à nouveau, car la propriété handleClick n'a pas changé.
Je pense que vous pourriez devenir trop obsédé par les rediffusions de React. Le bouton doit être rendu à nouveau car il handleClickdoit être modifié lorsqu'il est fireNewCallmodifié dans certains cas. Même si, handleClickne sera jamais changé. Il n'est pas nécessaire de penser à un nouveau rendu d'élément.
À peu près ce que Benjamin et Viet ont dit - dans votre code d'origine, une nouvelle fonction est assignée à handleClick sur chaque rendu. Vous pouvez utiliser React.useCallbackpour conserver la référence de fonction d'origine et ne la mettre à jour que lorsque quelque chose dans le tableau de dépendances change - dans ce cas, il suffit fireNewCalld'aller dans le tableau de dépendances.
Mais comme le dit Viet, ne soyez pas trop obsédé par cela. L'utilisation React.useCallbackpeut même ralentir votre code. Consultez Kent C. Dodds When to useMemo et useCallback post pour plus d'informations.