almessadi.
Zur Übersicht

React-Timer-Lecks treten auf, wenn Effekte arbeiten, die sie nie stoppen_

Intervalle, Beobachter und langlebige Browser-Callbacks können Arbeit im Arbeitsspeicher und CPU am Leben halten, nachdem die Komponente entfernt wurde, es sei denn, der Effekt reinigt sie ausdrücklich.

Veröffentlicht5. November 2024
Lesezeit8 min read

React-Komponenten verursachen keinen Speicherleck, weil sie häufig gerendert werden. Sie lecken, wenn etwas außerhalb von React weiterläuft, nachdem die Komponente verschwinden sollte. Timer sind eine der einfachsten Möglichkeiten, diesen Fehler zu erzeugen, da setInterval und setTimeout im Browser-Ereignissystem und nicht im Komponentenlebenszyklus von React leben.

Der klassische Timer-Leck

Das sieht harmlos aus:

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

Wenn die Komponente unmontiert wird, wird das Intervall weiterhin ausgelöst. Das bedeutet, dass der Callback, der erfasste Zustand und jede durch refreshData() ausgelöste Arbeit länger leben kann als beabsichtigt.

Die Behebung ist einfach:

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

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

Wo es schlimmer wird

Timer-Lecks werden kostspieliger, wenn der Callback auch Netzwerkoperationen startet:

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

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

Jetzt betrifft der Fehler nicht nur den Speicher. Es kann zu doppeltem Polling, verschwendeter CPU und Anfragen kommen, die noch ausgelöst werden, nachdem der Benutzer navigiert hat.

Bessere Ingenieurregel

Jeder Effekt, der eine langlebige Ressource erwirbt, sollte sie im gleichen Effekt freigeben:

  • Intervalle
  • Timeouts
  • Ereignislistener
  • Beobachter
  • Abonnements

Diese Regel ist einfach, aber sie überführt einen großen Prozentsatz der React-Leak-Fehler. Wenn eine Ressource das Rendern überlebt, sollte sie einen expliziten Aufräumweg haben.

Weiterführende Lektüre