Das Missverständnis über React Memory Leak!

Dec 08 2022
Ich habe diesen Artikel geschrieben, um das Missverständnis über Speicherlecks in React aufzuklären. Es gibt viele Artikel darüber, wie man Speicherlecks in React vermeidet, aber viele von ihnen verwenden ein Beispiel, das keine Speicherlecks verursacht.
Foto von Joe Zlomek auf Unsplash, das das Leck veranschaulicht.

Ich habe diesen Artikel geschrieben, um das Missverständnis über Speicherlecks in React aufzuklären. Es gibt viele Artikel darüber, wie man Speicherlecks in React vermeidet, aber viele von ihnen verwenden ein Beispiel, das keine Speicherlecks verursacht.

Schauen wir uns das oft verwendete Beispiel an:

import { useState, useEffect } from "react";
​
export const UserList = () => {
  const [users, setUsers] = useState(null);
​
  useEffect(() => {
    const getUsers = async () => {
      const usersResponse = await fetch("https://dummy-api.com/api/v1/users");
      setUsers(await usersResponse.json());
    };
    getUsers();
  }, []);
​
  return (
    <>
       ...my-jsx...
    </>
  );
};

– Warnung: Es kann keine React-Statusaktualisierung für eine nicht gemountete Komponente durchgeführt werden.

Stimmt es, dass dieser Fall Speicherlecks verursacht, wie uns die Nachricht sagt? Um es zu verstehen, benötigen wir ein grundlegendes Verständnis der Speicherverwaltung.

Speicherverwaltung

Jede Programmiersprache muss mit Speicher umgehen können. Bei Low-Level-Sprachen muss der Programmierer den Speicher manuell verwalten. In Hochsprachen wie JavaScript wird dies automatisch gehandhabt.

Das Konzept der Speicherverwaltung besteht aus drei Lebenszyklen, die unabhängig von der Sprache nahezu gleich sind.

  1. Den benötigten Speicher zuweisen
  2. Verwenden Sie den zugewiesenen Speicher
  3. Geben Sie den zugewiesenen Speicher frei, wenn er nicht benötigt wird

Freigabe des allokierten Speichers

Die Freigabe des allokierten Speichers bedeutet das Entfernen von Daten innerhalb des Speichers, die nicht mehr benötigt werden. Die Freigabe des zugewiesenen Speichers in JavaScript wird durch einen Garbage Collector (GC) erreicht, und daher müssen Entwickler die Freigabe des Speichers nicht manuell handhaben.

Das Freigeben von zugewiesenem Speicher durch Referenz ist das Hauptkonzept von Garbage Collectors. Beim Referenzkonzept geht es darum, ob ein Objekt von anderen Objekten referenziert wird oder nicht. Wenn das Objekt keine anderen Objekte hat, die darauf verweisen/zeigen, ist es für den GC sammelbar, den zugewiesenen Speicher freizugeben.

Zurück zum React-Beispiel

Jetzt wissen wir mehr über die Speicherverwaltung und können besser verstehen, warum es in dem Codebeispiel, das wir oben im Artikel gesehen haben, kein echtes Speicherleck gibt.

Was passiert also, wenn setState für eine nicht gemountete Komponente aufgerufen wird? Da der API-Aufruf ein Versprechen ist, das einmal aufgelöst wird, gibt es keine fortlaufenden Verweise mehr auf das Zustandsobjekt, nachdem es gesetzt wurde.

Wir haben gelernt, dass Objekte, auf die keine anderen Objekte verweisen, für die GC gesammelt werden können. Da der Zustand unseres Benutzers kein anderes Objekt hat, das darauf verweist, wird er gesammelt und aus dem zugewiesenen Speicher freigegeben. Daher ist die Nachricht, die wir über Speicherlecks gesehen haben, in diesem speziellen Szenario nicht wahr.

Wenn unsere Komponente eine WebSocket-Verbindung anstelle einer Promise-HTTP-Anforderung abonniert, würde es zu einem Speicherleck kommen. Es würde ein Speicherleck entstehen, da die abonnierte WebSocket-Verbindung weiterhin auf Ereignisse lauscht. Daher würde es ein anderes Objekt geben, das auf den Zustand verweist. Wie wir erfahren haben, können Objekte, die von einem anderen Objekt referenziert werden, nicht vom GC erfasst werden.

Fazit

Die Nachricht von React war ein Fehlalarm und hat Entwickler verwirrt, weil sie glaubten, sie hätten Speicherlecks bekommen, indem sie regelmäßige HTTP-Anfragen an das Backend stellten, wenn die Komponente ausgehängt wurde, bevor die HTTP-Anfrage geantwortet hatte.

React hat einen Pull Request gemergt, um die Fehlermeldung über Speicherlecks zu entfernen. Bitte schauen Sie sich den Pull-Request auf Github an,https://github.com/facebook/react/pull/22114für mehr Details.

Danke fürs Lesen!