Quicky React: N’abusez pas des « useEffect »

Nouvelle série d’articles

Nouvelle série d’articles baptisés « Quicky ». Ils portent ce nom car à priori, ils devraient être court 🙂 J’utiliserai aussi mon repository github où vous pourrez voir un code complet avec des commits pour chaque étape de refactoring… Des commentaires dans le code seront rajoutés pour bien montrer l’avant et l’après à chaque commit

TL;DR :

  • Evitez les useEffect en cascade (un useEffect qui va modifier un state qui va faire en sorte d’appeler un autre useEffect, etc…)
  • useMemo peut faire le job à la place
  • Bonus: Appeler plusieurs setState dans une méthode asynchrone n’est pas une bonne idée 🙂

Trop de useEffect

Voici un exemple de code qui me dit que parfois, les useEffect, c’est vraiment puant… Un useEffect qui « appelle » un autre

useEffect. C’est à devenir fou! Par exemple, cet exemple, où une liste « async » qui, une fois chargée change certains compteurs via un deuxième useEffect. Pour les besoin de la démo, le code a été simplifié et « bien sûr » que personne ne code comme cela, n’est-ce pas?

Code complet dispo (avec commentaires et explications des soucis) sur : https://github.com/Nikoms/clean-todo/commit/5be102ae9e2eed1a4affd9586d71c8b972c0df4d

Le problème avec cela, c’est qu’on a beaucoup trop de « render ». Sans aucune interaction, on en a déjà 3:

  • Avant le fetchTodosFromApi
  • Après le fetchTodosFromApi
  • Après avoir mis à jour les compteurs via refreshCounters

Pas de state -> pas de useEffect -> pas de re-render.

Et pourquoi pas se passer des state pour les deux compteurs?

Code complet:  https://github.com/Nikoms/clean-todo/commit/1a36045110ef98db5f2d8ab2ff43af0a5808c397

C’est bien, mais là, on va recalculer les compteurs à chaque render. C’est pas trop grave pour certaines parties de code, mais dans notre cas, partons dans l’idée que c’est un « gros process ».

useMemo si besoin…

Si les performances s’en font ressentir, on peut très bien utiliser useMemo:

Code complet: https://github.com/Nikoms/clean-todo/commit/09b942f07122323e7229b8bbf32064d7e851be12

 Ca fait le même job que le useEffect au début, sauf que le calcul ne nécessite pas un re-render.

Bonus point: Async useEffect

Un truc intéressant à savoir pour les useEffect qui exécute des setState dans une méthode async:

Code complet: https://github.com/Nikoms/clean-todo/commit/3a952053adcb4b9e12aa8140c6550daa5cf2dd24

Bien sûr que personne ne va écrire ce genre de code (la promise n’a aucun interêt), mais pour le fun: Savez vous combien de render il va y avoir? Au moment où mes todos changent, l’exécution du useEffect se fera à la vitesse de la lumière (car il n’y a rien à faire, si ce n’est lancer une Promise qui sera finie plus tard…).

Ensuite, il y aura autant de re-render qu’il y a de setState. Dans ce cas-ci, il y aura donc 2 render…

Dans un useEffect « classique » (non-async) par contre, il n’y aurait eu qu’un seul re-render, car React ne se re-render qu’à la fin du useEffect… Bon à savoir 🙂

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *