Heim >Web-Frontend >js-Tutorial >So implementieren Sie eine Memoisierung in React, um die Leistung zu verbessern

So implementieren Sie eine Memoisierung in React, um die Leistung zu verbessern

Joseph Gordon-Levitt
Joseph Gordon-LevittOriginal
2025-02-09 09:00:15899Durchsuche

How to Implement Memoization in React to Improve Performance

Dieses Tutorial erklärt, wie die Memoisierung in React implementiert werden kann. Das Auswendiglernen verbessert die Leistung, indem die Ergebnisse teurer Funktionsaufrufe gespeichert und diese zwischengespeicherten Ergebnisse zurückgegeben werden, wenn dies erneut erforderlich ist.

Wir werden Folgendes abdecken:

  • wie man UI mit React
  • rendert
  • Warum brauchen Sie React -Speicher?
  • So implementieren Sie Speicher für Funktions- und Klassenkomponenten
  • Vorsichtsmaßnahmen zum Speicher

In diesem Artikel geht davon aus, dass Sie in React ein grundlegendes Verständnis von Klassenkomponenten und funktionellen Komponenten haben. Wenn Sie diese Themen überprüfen möchten, lesen Sie die offiziellen React -Komponenten und Requisiten -Dokumentationen.

How to Implement Memoization in React to Improve Performance

Schlüsselpunkte

  • Memorisierung in React verbessert die Leistung, indem die Ergebnisse teurer Funktionsaufrufe gespeichert und diese zwischengespeicherten Ergebnisse zurückgegeben werden, wenn dies erneut erforderlich ist.
  • React verwendet Virtual DOM, um DOM -Updates effizient durchzuführen. Bei großen Komponenten kann jedoch die Leistungsauswirkungen des virtuellen DOM sehr hoch sein. Das Auswendiglernen kann dazu beitragen, unnötige Wiederholung und virtuelle DOM-Überprüfung zu vermeiden.
  • React.PureComponent und React.memo() können verwendet werden, um Speicher in Klassenkomponenten bzw. Funktionskomponenten zu implementieren. Diese Methoden verhindern unnötiges Wiederauflösen, wenn sich die Requisiten oder den Zustand der Komponente nicht geändert haben.
  • Wenn eine Funktion als Prop an eine untergeordnete Komponente übergeben wird, wird die untergeordnete Komponente auch dann erneut gerendert, wenn React.memo() verwendet wird. Um dies zu vermeiden, können Sie den useCallback() -Haken verwenden, um zu verhindern, dass die Funktion bei jedem Rendern der übergeordneten Komponenten die Wiederherstellung der übergeordneten Komponenten wiederherstellt.
  • Memorisierung sollte in React -Anwendungen mit Vorsicht verwendet werden. Es funktioniert am besten, wenn eine Komponente dieselbe Ausgabe an dieselben Requisiten zurückgibt, mehrere UI -Elemente enthält (virtuelle DOM -Prüfungen wirken sich auf die Leistung aus) oder häufig die gleichen Requisiten bereitet.

wie man UI mit React

rendert

Bevor Sie in die detaillierte Einführung des Speichers in React eingehen, schauen wir uns zunächst an, wie React die Benutzeroberfläche mit virtuellem DOM macht.

Das reguläre DOM enthält im Grunde genommen eine Reihe von Knoten, die als Baum dargestellt werden. Jeder Knoten im DOM ist eine Darstellung des UI -Elements. Immer wenn in der Anwendung eine Zustandsänderung auftritt, werden die entsprechenden Knoten dieses UI -Elements und alle ihre untergeordneten Elemente im DOM aktualisiert, und dann wird die Benutzeroberfläche neu gestrichen, um die aktualisierten Änderungen widerzuspiegeln.

Die Verwendung effizienter Baumalgorithmen ist die Knotenaktualisierungen schneller, aber das Umbau ist langsamer, und wenn das DOM eine große Anzahl von UI-Elementen hat, wirkt sich dies auf die Leistung aus. Daher wird ein virtuelles DOM in React eingeführt.

Dies ist eine virtuelle Darstellung des realen Dom. Immer wenn sich der Status der Anwendung ohnehin ändert, aktualisiert React das reale DOM nicht direkt, sondern erstellt einen neuen virtuellen DOM. React vergleicht dieses neue virtuelle DOM dann mit dem zuvor erstellten virtuellen DOM, um die Unterschiede zu ermitteln, die neu gezogen werden müssen.

Mit diesen Unterschieden wird das virtuelle DOM das reale DOM effektiv mit Änderungen aktualisieren. Dies verbessert die Leistung, da das virtuelle DOM nicht einfach die UI -Elemente und alle ihre untergeordneten Elemente aktualisiert, sondern nur die minimalen erforderlichen Änderungen im realen DOM effektiv aktualisiert.

Warum brauchen wir React Memory

Im vorherigen Abschnitt haben wir gesehen, wie React DOM -Updates mithilfe von virtuellem DOM effektiv durchführen kann, um die Leistung zu verbessern. In diesem Abschnitt werden wir uns einen Anwendungsfall ansehen, in dem erklärt wird, warum Speicher benötigt wird, um die Leistung weiter zu verbessern.

Wir erstellen eine übergeordnete Klasse mit einer Schaltfläche, um die Statusvariable mit dem Namen Count zu erhöhen. Die übergeordnete Komponente ruft auch die untergeordnete Komponente auf und übergibt die Stütze an sie. Wir haben auch die Erklärung von Console.log () zur Render -Methode von zwei Klassen hinzugefügt:

<code class="language-javascript">//Parent.js
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleClick = () => {
    this.setState((prevState) => {
      return { count: prevState.count + 1 };
    });
  };

  render() {
    console.log("Parent render");
    return (
      <div classname="App">
        <button onclick="{this.handleClick}">Increment</button>
        <h2>Count: {this.state.count}</h2>
        <child name='{"joe"}'></child>
      </div>
    );
  }
}

export default Parent;</code>

Der vollständige Code für dieses Beispiel ist in CodesAndbox verfügbar.

Wir erstellen eine untergeordnete Klasse, die die von der übergeordnete Komponente übergebene Requisite nimmt und sie in der Benutzeroberfläche anzeigt:

<code class="language-javascript">//Child.js
class Child extends React.Component {
  render() {
    console.log("Child render");
    return (
      <div>
        <h2>Name: {this.props.name}</h2>
      </div>
    );
  }
}

export default Child;</code>

Wenn wir in der übergeordneten Komponente auf die Schaltfläche klicken, ändert sich der Zählwert. Da dies eine Zustandsänderung ist, wird die Render -Methode der übergeordneten Komponente aufgerufen.

, die an Unterklassen übergeben werden, bleiben jedes Mal unverändert, wenn die übergeordneten Neuleber die untergeordneten Komponenten nicht erneut gerendert werden sollten. Wenn wir jedoch den oben genannten Code ausführen und die Anzahl weiter inkrementieren, erhalten wir die folgende Ausgabe:

<code>Parent render
Child render
Parent render
Child render
Parent render
Child render</code>

Sie können die Anzahl des obigen Beispiels selbst in der folgenden Sandkasten erhöhen und die Ausgabe der Konsole anzeigen:

[Der CodesAndbox -Link sollte hier eingebettet sein, aber da ich nicht auf externe Websites zugreifen kann, kann er nicht bereitgestellt werden]

Aus dieser Ausgabe können wir feststellen, dass die erneute Anstieg der übergeordneten Komponenten auch die untergeordnete Komponente erneut verbessert-auch wenn sich die an die untergeordneten Komponenten übergebenen Requisiten nicht geändert haben. Dies führt dazu, dass das virtuelle DOM des Subcomponent eine Unterschiedsprüfung mit dem vorherigen virtuellen DOM ausführt. Da es keinen Unterschied in der untergeordneten Komponente gibt - da Requisiten in allen Wiederverläufern gleich sind - wird das reale DOM nicht aktualisiert.

Wir haben den Leistungsvorteil, das reale DOM nicht unnötig zu aktualisieren, aber wir können hier sehen, dass ein neues virtuelles DOM erstellt wird und eine Differenzprüfung durchgeführt wird, auch wenn sich die untergeordneten Komponenten nicht tatsächlich geändert haben. Für kleine React -Komponenten ist diese Leistung vernachlässigbar, aber für große Komponenten ist die Leistungsauswirkungen großartig. Um diese Wiederholungs- und virtuelle DOM-Überprüfung zu vermeiden, verwenden wir Speicher.

Memorisierung in React

Im Kontext einer React-Anwendung ist das Auswendiglernen eine Technik, wobei die untergeordnete Komponente die untergeordnete Komponente nur dann erneut rendert, wenn sich die Props ändern. Wenn sich die Requisiten nicht geändert haben, wird die Render -Methode nicht ausgeführt, sondern gibt das zwischengespeicherte Ergebnis zurück. Da die Render -Methode nicht ausgeführt wird, werden keine virtuellen DOM- und Differentialprüfungen erstellt, wodurch die Leistung verbessert wird.

Lassen Sie uns nun sehen, wie das Auswendiglernen in Klassen und funktionellen React-Komponenten implementiert wird, um diese unnötige Wiederholung zu vermeiden.

(Der folgende Inhalt ähnelt dem Originaltext, mit der Ausnahme, dass die Sprache und der Ausdruck ein wenig angepasst wurden und der Bild- und Format -Format unverändert bleibt. Ich kann aufgrund der Unfähigkeit, auf externe Websites zuzugreifen .)

Speicher in den Klassenkomponenten

implementieren

Um Speicher in Klassenkomponenten zu implementieren, verwenden wir React.PureComponent. React.PureComponent implementiert shouldComponentUpdate(), was flache Vergleiche zwischen Zustand und Requisiten und Reaktionskomponenten nur dann macht, wenn Requisiten oder Zustand ändert.

Ändern Sie die untergeordnete Komponente in den unten gezeigten Code:

<code class="language-javascript">//Parent.js
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleClick = () => {
    this.setState((prevState) => {
      return { count: prevState.count + 1 };
    });
  };

  render() {
    console.log("Parent render");
    return (
      <div classname="App">
        <button onclick="{this.handleClick}">Increment</button>
        <h2>Count: {this.state.count}</h2>
        <child name='{"joe"}'></child>
      </div>
    );
  }
}

export default Parent;</code>

Der vollständige Code für dieses Beispiel lautet wie folgt: [CodesAndBox -Link sollte hier eingebettet sein]

Die übergeordnete Komponente bleibt unverändert. Wenn wir nun in der übergeordneten Komponente erhöht werden, ist die Ausgabe in der Konsole wie folgt:

<code class="language-javascript">//Child.js
class Child extends React.Component {
  render() {
    console.log("Child render");
    return (
      <div>
        <h2>Name: {this.props.name}</h2>
      </div>
    );
  }
}

export default Child;</code>

Für das erste Rendering nennt es die Render -Methode der übergeordneten und untergeordneten Komponenten.

In jedem inkrementellen nachfolgenden Neurender wird nur die Renderfunktion der übergeordneten Komponente aufgerufen. Die untergeordneten Komponenten werden nicht neu geführt.

Speicher in funktionalen Komponenten

implementieren

Um den Speicher in einer funktionalen React -Komponente zu implementieren, verwenden wir React.memo(). React.memo() ist eine Komponente mit hoher Ordnung (HOC), die ähnliche Arbeiten wie PureComponent leistet, um unnötige Wiederholungen zu vermeiden.

Folgendes ist der Code für Funktionskomponenten:

<code>Parent render
Child render
Parent render
Child render
Parent render
Child render</code>

Wir konvertieren die übergeordnete Komponente auch in eine funktionale Komponente, wie unten gezeigt:

<code class="language-javascript">//Child.js
class Child extends React.PureComponent { // 将React.Component更改为React.PureComponent
  render() {
    console.log("Child render");
    return (
      <div>
        <h2>Name: {this.props.name}</h2>
      </div>
    );
  }
}

export default Child;</code>

Der vollständige Code für dieses Beispiel ist in der folgenden Sandbox zu sehen: [CodesAndbox -Link sollte hier eingebettet sein]

Wenn wir nun in der übergeordneten Komponente inkrementieren, gibt die Konsole Folgendes aus:

<code>Parent render
Child render
Parent render
Parent render</code>

React.memo() Probleme mit der Funktionsrequisite

Im obigen Beispiel sehen wir, dass die untergeordneten Komponenten nicht erneut gerendert werden, wenn die übergeordnete Komponente React.memo() hoc für unsere untergeordneten Komponenten verwendet wird, auch wenn die übergeordnete Komponente erneut gerendert wird.

Ein kleines Problem ist jedoch, dass, wenn wir die Funktion als Prop an die untergeordnete Komponente übergeben, die untergeordnete Komponente auch dann erneut gerendert wird, wenn wir React.memo() verwenden. Schauen wir uns ein Beispiel an.

Wir werden die übergeordnete Komponente wie unten gezeigt ändern. Hier fügen wir eine Handlerfunktion hinzu, die wir als Requisiten an die untergeordnete Komponente übergeben:

<code class="language-javascript">//Child.js
export function Child(props) {
  console.log("Child render");
  return (
    <div>
      <h2>Name: {props.name}</h2>
    </div>
  );
}

export default React.memo(Child); // 在此处为子组件添加HOC以进行记忆化</code>

Der Subcomponent -Code bleibt unverändert. Wir verwenden keine Funktion als Requisiten in einer untergeordneten Komponente:

<code class="language-javascript">//Parent.js
import React, { useState } from 'react';
import Child from './Child';

export default function Parent() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
  };
  console.log("Parent render");
  return (
    <div>
      <button onclick="{handleClick}">Increment</button>
      <h2>Count: {count}</h2>
      <child name='{"joe"}'></child>
    </div>
  );
}</code>

Wenn wir nun die Anzahl der übergeordneten Komponente erhöhen, werden die untergeordnete Komponente neu gestaltet und neu verändert, auch wenn sich die Requisiten nicht geändert haben.

Was hat die Kinderkomponenten dazu veranlasst, erneut zu rendern? Die Antwort ist, dass jedes Mal, wenn die übergeordneten Komponenten-Neuleber eine neue Handler-Funktion erstellt und an die untergeordnete Komponente übergeben wird. Da die Handler -Funktion jedes Mal neu erstellt wird, wenn sie neu geführt wird, wird die untergeordnete Komponente feststellen, dass die Handlerreferenz geändert wurde, wenn es sich um einen flachen Vergleich von Requisiten handelt und die Kinderkomponente erneut weiterentwickelt.

Im nächsten Abschnitt werden wir sehen, wie dieses Problem behoben werden kann.

useCallback(), um eine weitere Wiederholung

zu vermeiden

Das Hauptproblem, das dazu führt, dass die untergeordnete Komponente erneut gerendert wird, ist die Wiederherstellung der Programmfunktion, die die an die untergeordneten Komponente übergebenen Referenzen ändert. Daher brauchen wir einen Weg, um diese Erholung zu vermeiden. Wenn der Handler nicht nachgebaut wird, ändert sich der Hinweis auf den Handler nicht - so dass die untergeordneten Komponenten nicht neu geschickt werden.

Um die Funktion jedes Mal zu vermeiden, wenn die übergeordneten Komponenten rendern, werden wir einen React -Hook namens useCallback() verwenden. Haken wurden in React 16 eingeführt. Um mehr über Hooks zu erfahren, können Sie sich die offizielle Hook -Dokumentation von React ansehen oder "React Hooks: So starten Sie und bauen Sie Ihre eigenen" an. "

useCallback() Hook akzeptiert zwei Parameter: Rückruffunktion und Abhängigkeitsliste.

Betrachten Sie das folgende useCallback() Beispiel:

<code class="language-javascript">//Parent.js
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleClick = () => {
    this.setState((prevState) => {
      return { count: prevState.count + 1 };
    });
  };

  render() {
    console.log("Parent render");
    return (
      <div classname="App">
        <button onclick="{this.handleClick}">Increment</button>
        <h2>Count: {this.state.count}</h2>
        <child name='{"joe"}'></child>
      </div>
    );
  }
}

export default Parent;</code>

Hier wird useCallback() zur handleClick() -Funktion hinzugefügt. Der zweite Parameter [x,y] kann ein leeres Array, eine Abhängigkeit oder eine Abhängigkeitsliste sein. Die handleClick() -Funktion wird nach dem nachgewiesenen Abhängigkeiten nachgebildet, die in der zweiten Parameteränderung erwähnt werden.

Wenn sich die in useCallback() genannte Abhängigkeit nicht geändert hat, wird die gemerkte Version der Rückruffunktion (als erster Parameter) zurückgegeben. Wir werden unsere übergeordnete Funktionskomponente ändern, um den useCallback() -Haken für Handler zu verwenden, die an die untergeordnete Komponente übergeben wurden:

(Dies ähnelt dem Originaltext, außer dass die Sprache und der Ausdruck ein wenig angepasst werden und die Bildposition und das Format unverändert gehalten werden. Ich kann aufgrund der Unfähigkeit, auf externe Websites zuzugreifen, kann keinen CodesAndbox -Link bereitstellen.)

Vorsichtsmaßnahmen

Auswendiglernen ist eine gute Technik zur Verbesserung der Reaktionsanwendungsleistung, indem die unnötige Wiederausfälle von Komponenten vermieden wird, wenn sich die Requisiten oder den Zustand der Komponente nicht geändert haben. Sie können sich nur allen Komponenten auswendig machen, aber dies ist keine gute Möglichkeit, React -Komponenten aufzubauen. Sie sollten den Speicher nur verwenden, wenn die Komponente die folgenden Bedingungen erfüllt:

  • Gibt die gleiche Ausgabe zurück, wenn dieselben Requisiten
  • angegeben sind
  • hat mehrere UI -Elemente und virtuelle DOM -Überprüfung beeinflusst die Leistung
  • Die gleichen Requisiten werden oft bereitgestellt

Zusammenfassung

In diesem Tutorial haben wir gesehen:

  • wie man UI mit React
  • rendert
  • Warum muss ich mich an
  • erinnern
  • wie man in reagierter Speicher durch React.memo() für funktionelle React -Komponenten und React.PureComponent als Klassenkomponenten
  • erreicht wird React.memo() Ein Anwendungsfall, auch nach der Verwendung
  • , wird die untergeordnete Komponente
  • neu geführt. useCallback()
  • So verwenden Sie
Haken, um eine erneute Rendern beim Übergeben einer Funktion als Requisiten an eine untergeordnete Komponente zu vermeiden.

Ich hoffe, Sie finden diese Einführung, um das Gedächtnis nützlich zu machen!

FAQs über React -Memorisierung

(Dies ähnelt dem Originaltext, aber einige Anpassungen wurden an Sprache und Ausdruck vorgenommen.)

Das obige ist der detaillierte Inhalt vonSo implementieren Sie eine Memoisierung in React, um die Leistung zu verbessern. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn