almessadi.
Retour à l'index

Les fuites de temporisation dans React se produisent lorsque les effets commencent un travail qu'ils n'arrêtent jamais_

Les intervalles, les observateurs et les rappels de navigateur de longue durée peuvent maintenir le travail de mémoire et de CPU en vie après le démontage, à moins que l'effet ne les nettoie explicitement.

Publié5 novembre 2024
Temps de lecture8 min read

Les composants React ne fuient pas de mémoire parce qu'ils se rendent fréquemment. Ils fuient lorsque quelque chose en dehors de React continue de fonctionner après que le composant aurait dû disparaître. Les temporisateurs sont l'un des moyens les plus simples de créer ce bogue car setInterval et setTimeout vivent dans le système d'événements du navigateur, pas dans le cycle de vie des composants de React.

La fuite de temporisation classique

Cela semble inoffensif :

useEffect(() => {
  const id = setInterval(() => {
    refreshData();
  }, 1000);
}, []);

Si le composant se démonte, l'intervalle continue de se déclencher. Cela signifie que le rappel, l'état capturé et tout travail déclenché par refreshData() peuvent rester actifs plus longtemps que prévu.

La solution est simple :

useEffect(() => {
  const id = setInterval(() => {
    refreshData();
  }, 1000);

  return () => clearInterval(id);
}, []);

Là où ça devient pire

Les fuites de temporisation deviennent plus coûteuses lorsque le rappel commence également un travail réseau :

useEffect(() => {
  const id = setInterval(() => {
    void refreshData();
  }, 5000);

  return () => clearInterval(id);
}, [refreshData]);

Maintenant, le bogue concerne non seulement la mémoire. Il peut entraîner un sondage dupliqué, un CPU gaspillé et des requêtes qui continuent d'être envoyées après que l'utilisateur ait navigué ailleurs.

Meilleure règle d'ingénierie

Tout effet qui acquiert une ressource de longue durée devrait la libérer dans le même effet :

  • intervalles
  • délais
  • écouteurs d'événements
  • observateurs
  • abonnements

Cette règle est simple, mais elle attrape un grand pourcentage des bogues de fuite dans React. Si une ressource survit au rendu, elle devrait avoir un chemin de nettoyage explicite.

Lectures supplémentaires