Aller au contenu
useEffect : les usages légitimesLecture : 0 %

useEffect : les usages légitimes

Le test qui sépare un effet légitime d'un effet à supprimer, les remplacements pour chaque famille d'effets abusifs, et les cas où il vaut mieux laisser l'effet en place.

Par Elias Varen7 min de lectureMembres

Dans une base React de quelques années, la majorité des useEffect peuvent être supprimés sans changer le comportement, et une bonne part des bugs intermittents de l'interface partent avec eux. Je ne donnerai pas de pourcentage ; le constat se refait chez vous, en une après-midi de revue, avec une seule question par effet.

Quel système extérieur à React cet effet synchronise-t-il ?

Si la réponse nomme quelque chose (le DOM manipulé à la main, une connexion réseau, une API du navigateur, un widget qui n'est pas en React), l'effet est légitime. Si la réponse est « un autre morceau d'état React » ou « ce qui doit se passer quand l'utilisateur clique », ce n'est pas un effet, c'est une dérivation ou un gestionnaire d'événement écrit au mauvais endroit.

Un rendu de trop, un déclencheur de trop

Un effet s'exécute après le rendu. Un effet qui écrit de l'état provoque donc un second rendu, et entre les deux l'écran a montré un état incohérent.

tsx
// Deux rendus, dont un faux
const [lignes, setLignes] = useState<Ligne[]>([]);
const [total, setTotal] = useState(0);

useEffect(() => {
  setTotal(lignes.reduce((s, l) => s + l.montant, 0));
}, [lignes]);

Le premier rendu affiche les nouvelles lignes avec l'ancien total, le second le bon total. Entre les deux, tout enfant qui lit total a calculé avec une valeur périmée, et tout effet d'un enfant qui dépend de total s'est exécuté une fois pour rien. Avec trois effets de ce type enchaînés, où A écrit ce que B observe et B ce que C observe, on obtient une cascade de quatre rendus dont l'ordre dépend de l'ordre de déclaration des hooks. C'est le terrain des bugs « ça clignote parfois » et « il faut cliquer deux fois ».

L'autre mécanisme de casse est le déclenchement implicite. Un gestionnaire d'événement s'exécute parce que l'utilisateur a agi. Un effet s'exécute parce qu'une dépendance a changé, quelle qu'en soit la cause, un clic, mais aussi un remontage, une navigation arrière, une restauration d'état ou le double montage du mode strict. Mettre dans un effet une logique qui devait répondre à un clic l'expose à tous les autres déclencheurs.

useEffect : les usages légitimes · Deepstack