Meilleures pratiques avec les crochets React
Publié: 2022-03-10 React Hooks est un nouvel ajout dans React 16.8 qui vous permet d'utiliser l'état et d'autres fonctionnalités de React sans écrire de composant de class
. En d'autres termes, les Hooks sont des fonctions qui vous permettent de « vous connecter » à l'état React et aux fonctionnalités de cycle de vie des composants fonctionnels. (Ils ne fonctionnent pas à l'intérieur des composants class
.)
React fournit quelques Hooks intégrés comme useState
. Vous pouvez également créer vos propres crochets pour réutiliser le comportement avec état entre différents composants. L'exemple ci-dessous montre un compteur dont l'état est géré à l'aide du crochet useState()
. Chaque fois que vous cliquez sur le bouton, nous utilisons setCount()
pour mettre à jour la valeur de count
par 1
.
Cet exemple affiche un compteur avec une valeur de 0
. Lorsque vous cliquez sur le bouton, il incrémente la valeur de 1
. La valeur initiale du composant est définie à l'aide useState
.
const [count, setCount] = useState(0)
Comme vous pouvez le voir, nous l'avons défini sur 0
. Ensuite, nous utilisons la méthode onClick()
pour appeler setCount
lorsque nous voulons incrémenter la valeur.
<button onClick={() => setCount(count + 1)}> Click me </button>
Avant la sortie de React Hooks, cet exemple aurait utilisé plus de lignes de code, car nous aurions dû utiliser un composant de class
.
Règles des crochets React
Avant de plonger dans les meilleures pratiques, nous devons comprendre les règles de React Hooks qui sont également quelques-uns des concepts fondamentaux des pratiques présentées dans cet article.
Les React Hooks sont des fonctions JavaScript, mais vous devez suivre deux règles lors de leur utilisation.
- Crochets d'appel au niveau supérieur ;
- Appelez uniquement les crochets à partir des composants React.
Remarque : Ces deux règles ont été introduites dans React Hooks, au lieu de faire partie de JavaScript lui-même.
Examinons ces règles plus en détail.
Crochets d'appel au niveau supérieur
N'appelez pas Hooks dans des boucles, des conditions ou des fonctions imbriquées. Utilisez toujours les crochets au niveau supérieur de votre fonction React. En suivant cette règle, vous vous assurez que les crochets sont appelés dans le même ordre à chaque rendu d'un composant. C'est ce qui permet à React de conserver correctement l'état des Hooks entre plusieurs useState
et useEffect
.
Créons un composant Form
qui aura deux états :
-
accountName
-
accountDetail
Ces états auront des valeurs par défaut, nous utiliserons le crochet useEffect
pour conserver l'état soit dans le stockage local de notre navigateur, soit dans le titre de notre document.
Maintenant, ce composant sera peut-être capable de gérer avec succès son état s'il reste le même entre plusieurs appels de useState
et useEffect
.
function Form() { // 1. Use the accountName state variable const [accountName, setAccountName] = useState('David'); // 2. Use an effect for persisting the form useEffect(function persistForm() { localStorage.setItem('formData', accountName); }); // 3. Use the accountDetail state variable const [accountDetail, setAccountDetail] = useState('Active'); // 4. Use an effect for updating the title useEffect(function updateStatus() { document.title = accountName + ' ' + accountDetail; }); // ... }
Si l'ordre de nos Hooks change (ce qui peut être possible lorsqu'ils sont appelés dans des boucles ou des conditionnels), React aura du mal à comprendre comment préserver l'état de notre composant.
// ------------ useState('David') // 1. Initialize the accountName state variable with 'David' useEffect(persistForm) // 2. Add an effect for persisting the form useState('Active') // 3. Initialize the accountdetail state variable with 'Active' useEffect(updateStatus) // 4. Add an effect for updating the status // ------------- // Second render // ------------- useState('David') // 1. Read the accountName state variable (argument is ignored) useEffect(persistForm) // 2. Replace the effect for persisting the form useState('Active') // 3. Read the accountDetail state variable (argument is ignored) useEffect(updateStatus) // 4. Replace the effect for updating the status // ...
C'est l'ordre que React suit pour appeler nos crochets. Puisque la commande reste la même, elle pourra préserver l'état de notre composant. Mais que se passe-t-il si nous plaçons un appel Hook dans une condition ?
// We're breaking the first rule by using a Hook in a condition if (accountName !== '') { useEffect(function persistForm() { localStorage.setItem('formData', accountName); }); }
La condition accountName !== ''
est true
sur le premier rendu, donc nous exécutons ce Hook. Cependant, lors du rendu suivant, l'utilisateur peut effacer le formulaire, rendant la condition false
. Maintenant que nous ignorons ce crochet lors du rendu, l'ordre des appels de crochet devient différent :
useState('David') // 1. Read the accountName state variable (argument is ignored) // useEffect(persistForm) // This Hook was skipped! useState('Active') // 2 (but was 3). Fail to read the accountDetails state variable useEffect(updateStatus) // 3 (but was 4). Fail to replace the effect
React ne saurait pas quoi renvoyer pour le deuxième appel useState
Hook. React s'attendait à ce que le deuxième appel de Hook dans ce composant corresponde à l'effet persistForm
, tout comme lors du rendu précédent — mais ce n'est plus le cas. À partir de ce moment, chaque prochain appel Hook
après celui que nous avons ignoré se décalerait également d'un, ce qui entraînerait des bogues.
C'est pourquoi les Hooks doivent être appelés au plus haut niveau de nos composants. Si nous voulons exécuter un effet de manière conditionnelle, nous pouvons mettre cette condition dans notre Hook.
Remarque : consultez les documents React Hook pour en savoir plus sur ce sujet.
Appeler uniquement les hooks à partir des composants React
N'appelez pas Hooks à partir de fonctions JavaScript classiques. Au lieu de cela, vous pouvez appeler Hooks à partir des composants de la fonction React. Voyons ci-dessous la différence entre la fonction JavaScript et le composant React :
Fonction JavaScript
import { useState } = "react"; function toCelsius(fahrenheit) { const [name, setName] = useState("David"); return (5/9) * (fahrenheit-32); } document.getElementById("demo").innerHTML = toCelsius;
Ici, nous importons le hook useState
du package React, puis nous déclarons notre fonction. Mais ce n'est pas valide car ce n'est pas un composant React.
Fonction de réaction
import React, { useState} from "react"; import ReactDOM from "react-dom"; function Account(props) { const [name, setName] = useState("David"); return <p>Hello, {name}! The price is <b>{props.total}</b> and the total amount is <b>{props.amount}</b></p> } ReactDom.render( <Account total={20} amount={5000} />, document.getElementById('root') );
Même si le corps des deux semble similaire, ce dernier devient un composant lorsque nous importons React dans le fichier. C'est ce qui nous permet d'utiliser des choses comme les crochets JSX et React à l'intérieur.
S'il vous arrivait d'importer votre hook préféré sans importer React (ce qui en fait une fonction normale), vous ne pourrez pas utiliser le Hook que vous avez importé car le Hook n'est accessible que dans le composant React.
Crochets d'appel à partir de crochets personnalisés
Un Hook personnalisé est une fonction JavaScript dont le nom commence par use
et qui peut appeler d'autres Hooks. Par exemple, useUserName
est utilisé sous un crochet personnalisé qui appelle les crochets useState
et useEffect
. Il récupère les données d'une API, parcourt les données et appelle setIsPresent()
si le nom d'utilisateur spécifique qu'il a reçu est présent dans les données de l'API.
export default function useUserName(userName) { const [isPresent, setIsPresent] = useState(false); useEffect(() => { const data = MockedApi.fetchData(); data.then((res) => { res.forEach((e) => { if (e.name === userName) { setIsPresent(true); } }); }); }); return isPresent; }
Nous pouvons ensuite continuer à réutiliser la fonctionnalité de ce crochet à d'autres endroits où nous en avons besoin dans notre application. Dans de tels endroits, sauf en cas de besoin, nous n'avons plus besoin d'appeler useState
ou useEffect
.
En suivant cette règle, vous vous assurez que toute la logique avec état d'un composant est clairement visible à partir de son code source.
Plugin ESLintComment
Le plugin ESLint appelé eslint-plugin-react-hooks
applique les règles ci-dessus. Cela est pratique pour faire respecter les règles lorsque vous travaillez sur un projet. Je vous suggère d'utiliser ce plugin lorsque vous travaillez sur votre projet, en particulier lorsque vous travaillez avec d'autres. Vous pouvez ajouter ce plugin à votre projet si vous souhaitez l'essayer :
// Your ESLint configuration { "plugins": [ // ... "react-hooks" ], "rules": { // ... "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies } }
Ce plugin est inclus par défaut dans Create React App. Vous n'avez donc pas besoin de l'ajouter si vous démarrez vos applications React à l'aide de Create-React-App.
Penser en crochets
Examinons brièvement les composants de class
et les composants fonctionnels (avec Hooks), avant de plonger dans les quelques bonnes pratiques Hooks.
La façon la plus simple de définir un composant dans React est d'écrire une fonction JavaScript qui renvoie un élément React :
function Welcome(props) { return <h1>Hello, {props.name}</h1>; }
Le composant Welcome
accepte props
qui sont un objet qui contient des données et renvoie un élément React. Nous pouvons ensuite importer et restituer ce composant dans un autre composant.
Le composant class
utilise une méthodologie de programmation appelée Encapsulation , ce qui signifie essentiellement que tout ce qui concerne le composant de classe y vivra. Les méthodes de cycle de vie ( constructors
, componentDidMount()
, render
, etc.) donnent aux composants une structure prévisible.
L'encapsulation est l'un des fondamentaux de la POO ( O bject- O riented P rogramming). Il fait référence au regroupement de données dans les méthodes qui opèrent sur ces données et est utilisé pour masquer les valeurs ou l'état d'un objet de données structuré à l'intérieur d'une classe, empêchant ainsi l'accès direct des parties non autorisées.
Avec les crochets, la composition d'un composant passe d'une combinaison de crochets de cycle de vie à des fonctionnalités avec un rendu à la fin.
Composant de fonction
L'exemple ci-dessous montre comment les crochets personnalisés peuvent être utilisés dans un composant fonctionnel (sans montrer ce qu'est le corps). Cependant, ce qu'il fait ou peut faire n'est pas limité. Il peut s'agir d'instancier des variables d'état, de consommer des contextes, d'abonner le composant à divers effets secondaires - ou tout ce qui précède si vous utilisez un hook personnalisé !
function { useHook{...}; useHook{...}; useHook{...}; return (
...); }
Composant de classe
Un composant class
vous oblige à étendre à partir de React.Component
et à créer une fonction de render
qui renvoie un élément React. Cela nécessite plus de code mais vous apportera également certains avantages.
class { constructor(props) {...} componentDidMount() {...} componentWillUnmount() {...} render() {...} }
L'utilisation de composants fonctionnels dans React présente certains avantages :
- Il sera plus facile de séparer les composants de conteneur et de présentation, car vous devez réfléchir davantage à l'état de votre composant si vous n'avez pas accès à
setState()
dans votre composant. - Les composants fonctionnels sont beaucoup plus faciles à lire et à tester car ce sont de simples fonctions JavaScript sans état ni crochets de cycle de vie.
- Vous vous retrouvez avec moins de code.
- L'équipe React a mentionné qu'il pourrait y avoir une amélioration des performances des composants fonctionnels dans les futures versions de React.
Cela conduit à la première meilleure pratique lors de l'utilisation de React Hooks.
Meilleures pratiques pour les hooks
1. Simplifiez vos crochets
Garder React Hooks simple vous donnera le pouvoir de contrôler et de manipuler efficacement ce qui se passe dans un composant tout au long de sa durée de vie. Evitez autant que possible d'écrire des Hooks personnalisés ; vous pouvez incorporer un useState()
ou useEffect()
au lieu de créer votre propre crochet.
Si vous vous retrouvez à utiliser un tas de crochets personnalisés dont les fonctionnalités sont liées, vous pouvez créer un crochet personnalisé qui agit comme un wrapper pour ceux-ci. Jetons un coup d'œil à deux composants fonctionnels différents avec des crochets ci-dessous.
Composant fonctionnel v1
function { useHook(...); useHook(...); useHook(...); return( <div>...</div> ); }
Composant fonctionnel v2
function { useCustomHook(...); useHook(...); useHook(...); return( <div>...</div> ); }
v2 est une meilleure version car elle garde le hook simple et tous les autres useHook
s sont en ligne en conséquence. Cela nous permet de créer des fonctionnalités qui peuvent être réutilisées sur différents composants et nous donne également plus de pouvoir pour contrôler et manipuler efficacement nos composants. Au lieu d'adopter la v1 dans laquelle nos composants sont jonchés de Hooks, vous devriez utiliser la v2 qui facilitera le débogage et rendra votre code plus propre.
2. Organisez et structurez vos crochets
L'un des avantages de React Hooks est la possibilité d'écrire moins de code facile à lire. Dans certains cas, la quantité de useEffect()
et useState()
peut encore prêter à confusion. Lorsque vous gardez votre composant organisé, cela contribuera à la lisibilité et à garder le flux de vos composants cohérent et prévisible. Si vos Hooks personnalisés sont trop compliqués, vous pouvez toujours les décomposer en Hooks sous-personnalisés. Extrayez la logique de votre composant vers des Hooks personnalisés pour rendre votre code lisible.
3. Utilisez des extraits de crochets React
React Hooks Snippets est une extension Visual Studio Code pour rendre React Hooks plus facile et plus rapide. Actuellement, cinq crochets sont pris en charge :
-
useState()
-
useEffect()
-
useContext()
-
useCallback()
-
useMemo()
D'autres extraits ont également été ajoutés. J'ai essayé de travailler avec ces crochets et cela a été l'une des meilleures pratiques que j'ai personnellement utilisées en travaillant avec eux.
Vous pouvez ajouter des extraits React Hooks à votre projet de deux manières :
- Commander
Lancez VS Code Quick open ( Ctrl + P ), collezext install ALDuncanson.react-hooks-snippets
et appuyez sur Enter . - Marché des extensions
Lancez 'VS Code Extension Marketplace' ( Ctrl + Shift + X ) et recherchez 'React Hook Snippets'. Ensuite, recherchez l'icône 'Alduncanson'.
Je recommande le premier extrait. En savoir plus sur les extraits ici ou vérifier les derniers extraits Hooks ici.
4. Tenez compte des règles des crochets
Efforcez-vous de toujours tenir compte des deux règles de Hooks que nous avons apprises plus tôt lorsque vous travaillez avec React Hooks.
- N'appelez vos crochets qu'au niveau supérieur. N'appelez pas Hooks dans des boucles, des conditions ou des fonctions imbriquées.
- Appelez toujours les crochets à partir des composants de la fonction React ou à partir des crochets personnalisés, n'appelez pas les crochets à partir des fonctions JavaScript régulières.
Le plugin ESlint appelé eslint-plugin-react-hooks
applique ces deux règles, vous pouvez ajouter ce plugin à votre projet si vous le souhaitez comme nous l'expliquons ci-dessus dans la section règles des crochets.
Les meilleures pratiques n'ont pas été entièrement résolues car les crochets sont encore relativement nouveaux. L'adoption doit donc être prise avec la précaution que l'on prendrait en adoptant n'importe quelle technologie précoce. Dans cet esprit, les crochets sont la voie pour l'avenir de React.
Conclusion
J'espère que vous avez apprécié ce tutoriel. Nous avons appris les deux règles les plus importantes de React Hooks et comment penser efficacement dans Hooks. Nous avons examiné les composants fonctionnels et certaines des meilleures pratiques pour écrire des crochets de manière appropriée et efficace. Aussi brèves que soient les règles, il est important d'en faire votre boussole lors de la rédaction des règles. Si vous avez tendance à l'oublier, vous pouvez utiliser le plugin ESLint pour l'appliquer.
J'espère que vous tirerez parti de toutes les leçons apprises ici dans votre prochain projet React. Bonne chance!
Ressources
- "Présentation des crochets", React Docs
- "Composants fonctionnels vs composants de classe dans React", David Joch, Medium
- "Mixines considérées comme nocives", Dan Abramov, blog React
- "React Hooks : meilleures pratiques et changement d'état d'esprit", Bryan Manuele, Medium
- « Réagissez les extraits de crochets pour le code VS », Anthony Davis, Visual Code Marketplace