Detaillierte Erklärung der Rolle des Schlüssels in React

Detaillierte Erklärung der Rolle des Schlüssels in React

Um die Rolle des Schlüssels in React zu verstehen, können wir mit dem Wert des Schlüssels beginnen. Der Wert des Schlüssels kann in drei Typen unterteilt werden: unbestimmter Wert, Indexwert und bestimmter und eindeutiger Wert.

Im folgenden Code ist der Wert des Schlüssels ein unbestimmter Wert (Math.random())

Frage: Wird die Farbe des Bereichs rot, wenn auf die Schaltfläche geklickt wird?

importiere React, { useState } von 'react';

Funktion App() {
  const [initMap, setInitMap] = useState([1,2,3,4]);
  const handleClick = () => {
    setInitMap([1,2,3,4])
    var spanEle = document.getElementsByTagName('span');
    Array.von(spanEle).map(it => it.style.color = "rot")
  }
  
  zurückkehren (
    <div Klassenname="App" id="App">
      {
        initMap.map((it,index) => <div Schlüssel={Math.random()}><span>Farbe</span></div>)
      }
      <button bei Klick={() => handleClick()}></button>
    </div>
  );
}

Standard-App exportieren;

Die Antwort ist: Nein

Dieses Problem betrifft den React-Rendering-Mechanismus und den Diff-Algorithmus

Auf der offiziellen Website finden Sie die folgenden Regeln für Diff:

  • Wenn sich der Elementtyp ändert, wird er zerstört und neu erstellt
  • Wenn der Elementtyp unverändert bleibt, vergleichen Sie die Attribute
  • Wenn der Komponentenelementtyp unverändert bleibt, bestimmen Sie die untergeordneten Knoten rekursiv über Requisiten
  • Vergleichen Sie untergeordnete Knoten rekursiv. Wenn der untergeordnete Knoten eine Liste ist, beurteilen Sie nach Schlüssel und Eigenschaften. Wenn die Schlüssel konsistent sind, aktualisieren Sie sie. Wenn die Schlüssel inkonsistent sind, zerstören Sie sie und erstellen Sie sie neu.

Analysieren Sie die oben genannten Probleme:

Wenn auf die Schaltfläche geklickt wird, führt setInitMap([1,2,3,4]) zum Rendern aus. Beim Rendern wird ein neuer virtueller DOM generiert. Das zu diesem Zeitpunkt erhaltene Span-Element ist jedoch das vorherige Element (da setInitMap asynchron ausgeführt wird), sodass die neuen und alten DOMs verglichen werden.

Im Code initMap.map((it,index) => <div key={Math.random()}><span>color</span></div>)

Das Div hier ist eine Liste. Im Vergleich zur vierten Diff-Regel bestimmt React anhand des Schlüssels, ob das reale DOM aktualisiert werden soll. key={Math.random()}, wenn die Werte des neuen und alten DOMs inkonsistent sind, wird das Div neu generiert. Wir haben dem Element vor dem Update einen roten Stil hinzugefügt, daher wird das neu erstellte Element diesen Stil nicht haben. Der Effekt ist wie folgt

Der zweite Fall: Der Schlüsselwert ist der Indexwert

Das Ergebnis unserer obigen Analyse ist, dass das Div-Element aufgrund der Schlüsseländerung beim Rendern neu generiert wird. Was passiert, wenn der Schlüssel vor und nach dem Rendern unverändert bleibt? Ändern Sie beispielsweise den Schlüssel in den Index

Frage: Ändert sich die Farbe des Bereichs, nachdem in diesem Code auf die Schaltfläche geklickt wurde?

zurückkehren (
    <div Klassenname="App" id="App">
      <Drehen spinning={spin}></Drehen>
      {
        initMap.map((it,index) => <div Schlüssel={index}><span>Farbe</span></div>)
      }
      <button bei Klick={() => handleClick()}></button>
    </div>
  );

Antwort: Ja

Analyse: Da der Index vor und nach dem Rendern unverändert bleibt, wird das Div nicht neu generiert. Vergleichen Sie dann das Span-Element. Die Attribute des Span-Elements ändern sich vor und nach dem Rendern, sodass React nur neue Attribute auf das Span-Element anwendet, diese jedoch weiterhin auf das vorherige Element verweisen.

Der dritte Fall: Der Schlüsselwert ist bestimmt und eindeutig:

In diesem Beispiel ändert sich die Farbe des Bereichs, wenn der Schlüssel auf Index gesetzt wird. Bei der Verwendung von Schlüsseln empfiehlt die offizielle React-Website jedoch nicht, Index zu verwenden.

Ändern Sie den obigen Code

  const [initMap, setInitMap] = useState([1,2,3,4]);
  const handleClick = () => {
    setInitMap([3,2,1,4])
  }
  zurückkehren (
    <div Klassenname="App" id="App">
      {
        initMap.map((it,index) => <div key={index}><input type="radio" />{it}</div>)
      }
      <button onClick={() => handleClick()}>Klick</button>
    </div>
  );
}

Wählen Sie beim Initialisieren die Schaltfläche mit dem Wert 3

Klicken Sie auf die Schaltfläche

Der erwartete Effekt besteht darin, dass die Schaltfläche mit dem Wert 3 immer noch ausgewählt ist, jetzt aber zur Schaltfläche mit dem Wert 1 wird.

analysieren:

  1. setState bewirkt rendern
  2. Der Index des Div ändert sich nicht, daher wird das Div nicht neu generiert, und die Eingabe wird nicht durch Status und Eigenschaften gesteuert, daher ändert sich der Status des Elements nicht
  3. Das einzige, was sich ändert, ist, dass es vom Staat beeinflusst wird

Wenn wir den gewünschten Effekt erzielen wollen, müssen wir einen eindeutigen und sicheren Schlüssel festlegen

Prüfung 1:

{
   initMap.map((it) => <div key={it}><input type="radio" />{it}</div>)
}

Wählen Sie während der Initialisierung die dritte Schaltfläche

Klicken Sie auf die Schaltfläche

Dies ist der erwartete Effekt

Überlegen Sie, welche Auswirkungen es hat, wenn Sie den Schlüssel auf Math.random() setzen? Bleibt der Zustand der Schaltfläche erhalten?

Vor dem Klicken:

Nach dem Klicken:

Der Radiozustand bleibt nicht erhalten.

Durch die obigen Beispiele können wir wahrscheinlich die Rolle des Schlüssels in React verstehen. Der folgende Inhalt ist eine Erweiterung der Wissenspunkte von React

Erweiterter Inhalt: Der Code am Anfang des Artikels beinhaltet auch zwei weitere Wissenspunkte von React, einer sind die oben erwähnten React-Rendering-Bedingungen und der andere ist der Betrieb des realen DOM.

Erweiterung 1: React-Rendering-Bedingungen

importiere './App.css';
importiere React, { useState } von 'react';

Funktion App() {
  const [initMap, setInitMap] = useState([1,2,3,4]);
  const [spin, setzeSpin] = useState(false);
  const handleClick = () => {
    setSpin(true); //Geänderter Teil var spanEle = document.getElementsByTagName('span');
    Array.von(spanEle).map(it => it.style.color = "rot")
    setSpin(false); //Teil ändern}
  
  zurückkehren (
    <div Klassenname="App" id="App">
      <Drehen spinning={spin}></Drehen>
      {
        initMap.map((it,index) => <div Schlüssel={Math.random()}><span>{it}</span></div>)
      }
      <button bei Klick={() => handleClick()}></button>
    </div>
  );
}

Standard-App exportieren;

Die Testergebnisse vor dem Klicken sind wie folgt:

Nach dem Klicken:

In diesem Code verwendet der Schlüssel von div immer noch Math.random(), aber der Status von initMap hat sich nicht geändert, sodass es nicht erneut gerendert wird. Zu diesem Zeitpunkt wird div nicht zerstört und neu erstellt.

Erweiterung 2: Ist es möglich, auf dem echten DOM zu operieren?

In React besteht die Entstehung des virtuellen DOM darin, den Aufwand für Operationen am realen DOM zu reduzieren, da das reale DOM-Element ein komplexeres Objekt ist und die Operationen viele Berechnungen erfordern. Im obigen Code manipulieren wir direkt den DOM-Knoten und ändern den Stil, was nicht ratsam ist. Da React Seiten basierend auf Status- und Eigenschaftenänderungen rendert, ist es besser, das Seiten-Rendering über den Status zu steuern.

Der geänderte Code lautet wie folgt:

Funktion App() {
  const [initMap, setInitMap] = useState([1,2,3,4]);
  const [spin, setzeSpin] = useState(false);
  const [showColor, setShowColor] = useState(false);
  const handleClick = () => {
    setInitMap([3,2,1,4]);
    setZeigeFarbe(true);
  }
  
  zurückkehren (
    <div Klassenname="App" id="App">
      <Drehen drehend={spin}>
      {
        initMap.map((it,index) => <div key={Math.random()}><span className={showColor && 'span-color'}>Farbe</span></div>)
      }
      </Drehen>
      <button onClick={() => handleClick()}>Klick</button>
    </div>
  );
}

Zu diesem Zeitpunkt ist span eine kontrollierte Komponente, und das Rendering des Elements kann durch den Status von showColor gesteuert werden.

Vor dem Klicken:

Nach dem Klicken:

Nachdem Sie den Status zur Steuerung des Renderings verwendet haben, wird die Codemenge reduziert und die Ergebnisse entsprechen den Erwartungen

Zusammenfassen

  1. Stellen Sie bei der Verwendung von Schlüsseln sicher, dass die Schlüssel eindeutig und deterministisch sind. Wenn der Schlüsselwert Math.random() ist, kann dies dazu führen, dass die Komponente neu erstellt wird, wodurch vorherige Vorgänge am Element ungültig werden.
  2. Versuchen Sie beim Rendern einer Seite, das reale DOM nicht zu manipulieren und verwenden Sie den Status zum Aktualisieren der Seite

Oben finden Sie eine ausführliche Erläuterung der Rolle des Schlüssels in React. Weitere Informationen zur Rolle des React-Schlüssels finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • React Native meldet den Fehler „Ein Parameter vom Typ ‚NSArray<id<RCTBridgeModule>> kann nicht initialisiert werden“ (Lösung)
  • Zusammenfassung der React-Grundlagen
  • Detaillierte Erläuterung der Datenübertragung zwischen React-Elternkomponenten und -Kindkomponenten
  • Detaillierte Hinweise zu React für Einsteiger

<<:  So konfigurieren Sie die bidirektionale Zertifikatsüberprüfung auf dem Nginx-Proxyserver

>>:  MySQL 5.7.18 Master-Slave-Replikations-Setup (ein Master und ein Slave) Tutorial mit ausführlicher Erklärung

Artikel empfehlen

Grundlegende Verwendung von exists, in und any in MySQL

【1】existiert Verwenden Sie eine Schleife, um die ...

Detaillierte Analyse von or, in, union und Indexoptimierung in MySQL

Dieser Artikel entstand aus der Hausaufgabe „Erle...

jQuery implementiert das Bouncing-Ball-Spiel

In diesem Artikel wird der spezifische Code von j...

CocosCreator Universal Framework Design Network

Inhaltsverzeichnis Vorwort WebSocket verwenden Er...

So verwenden Sie die Shell, um Batchvorgänge auf mehreren Servern auszuführen

Inhaltsverzeichnis SSH-Protokoll SSH Verbindungsp...

Detaillierte Analyse des MySQL 8.0-Redo-Logs

Inhaltsverzeichnis Vorwort Generierung eines Redo...

Eine kurze Diskussion zum Problem von Daten mit Nullwerten in der MySQL-Datenbank

Standardmäßig akzeptiert MySQL das Einfügen von 0...

So implementieren Sie geplante MySQL-Aufgaben zur Datensicherung unter Linux

Vorwort Backup ist die Grundlage der Notfallwiede...

Die Bedeutung der 5 Leerzeichenarten in HTML

HTML bietet fünf Leerzeichen mit unterschiedliche...

Detaillierte Erklärung zum Erstellen einer aktualisierbaren Ansicht in MySQL

Dieser Artikel beschreibt anhand eines Beispiels,...

Reacts Übergang von Klassen zu Hooks

Inhaltsverzeichnis ReagierenHooks Vorwort WarumHo...