Manipulation des DOM mit Refs
React aktualisiert automatisch dasDOM, um es mit deiner Render-Ausgabe abzugleichen, daher müssen deine Komponenten es oft nicht direkt manipulieren. Manchmal benötigst du jedoch Zugriff auf die von React verwalteten DOM-Elemente – beispielsweise, um einen Knoten zu fokussieren, zu ihm zu scrollen oder seine Größe und Position zu messen. In React gibt es keine eingebaute Möglichkeit, diese Dinge zu tun, daher benötigst du einenRefauf den DOM-Knoten.
Sie werden lernen
- Wie du mit dem
ref-Attribut auf einen von React verwalteten DOM-Knoten zugreifst - Wie sich das JSX-Attribut
refauf den HookuseRefbezieht - Wie du auf den DOM-Knoten einer anderen Komponente zugreifst
- In welchen Fällen es sicher ist, das von React verwaltete DOM zu ändern
Einen Ref auf den Knoten erhalten
Um auf einen von React verwalteten DOM-Knoten zuzugreifen, importiere zunächst den HookuseRef:
Deklariere dann damit einen Ref innerhalb deiner Komponente:
Übergib schließlich deinen Ref alsref-Attribut an das JSX-Tag, für das du den DOM-Knoten erhalten möchtest:
Der HookuseRefgibt ein Objekt mit einer einzigen Eigenschaft namenscurrentzurück. Anfangs istmyRef.current null. Wenn React einen DOM-Knoten für dieses<div>erstellt, platziert React eine Referenz auf diesen Knoten inmyRef.current. Du kannst dann von deinenEvent-Handlernaus auf diesen DOM-Knoten zugreifen und die darauf definierten integriertenBrowser-APIsverwenden.
Beispiel: Fokussieren einer Texteingabe
In diesem Beispiel wird durch Klicken auf den Button die Eingabe fokussiert:
So wird dies implementiert:
- Deklariere
inputRefmit dem HookuseRef. - Übergib ihn als
<input ref={inputRef}>. Dies teilt React mit,den DOM-Knoten dieses<input>ininputRef.currentzu platzieren. - Lies in der Funktion
handleClickden Eingabe-DOM-Knoten ausinputRef.currentund rufefocus()darauf mitinputRef.current.focus()auf. - Übergib den Event-Handler
handleClickmitonClickan den<button>.
Während DOM-Manipulation der häufigste Anwendungsfall für Refs ist, kann der HookuseRefauch zum Speichern anderer Dinge außerhalb von React verwendet werden, wie Timer-IDs. Ähnlich wie State bleiben Refs zwischen Renders erhalten. Refs sind wie State-Variablen, die beim Setzen keine Neu-Render auslösen. Lies mehr über Refs unterReferenzieren von Werten mit Refs.
Beispiel: Zu einem Element scrollen
Du kannst mehr als einen Ref in einer Komponente haben. In diesem Beispiel gibt es einen Karussell mit drei Bildern. Jeder Button zentriert ein Bild, indem er die Browser-MethodescrollIntoView()auf dem entsprechenden DOM-Knoten aufruft:
Auf DOM-Knoten einer anderen Komponente zugreifen
Fallstrick
Refs sind eine Notlösung. Das manuelle Manipulieren der DOM-Knoteneiner anderenKomponente kann deinen Code fragil machen.
Du kannst Refs von einer Elternkomponente an Kindkomponenten übergeben,genau wie jede andere Prop.
Im obigen Beispiel wird eine Ref in der ElternkomponenteMyFormerstellt und an die KindkomponenteMyInputübergeben.MyInputleitet die Ref dann an<input>weiter. Da<input>eineeingebaute Komponenteist, setzt React die.current-Eigenschaft der Ref auf das<input>-DOM-Element.
Die inMyFormerstellteinputRefzeigt nun auf das<input>-DOM-Element, das vonMyInputzurückgegeben wird. Ein inMyFormerstellter Klick-Handler kann aufinputRefzugreifen undfocus()aufrufen, um den Fokus auf das<input>zu setzen.
Wann React die Refs anfügt
In React wird jedes Update inzwei Phasenunterteilt:
- Während desRendernsruft React deine Komponenten auf, um herauszufinden, was auf dem Bildschirm angezeigt werden soll.
- Während desCommitswendet React die Änderungen auf das DOM an.
Im Allgemeinensolltest du nichtwährend des Renderns auf Refs zugreifen. Das gilt auch für Refs, die DOM-Knoten halten. Während des ersten Renderlaufs wurden die DOM-Knoten noch nicht erstellt, daher istref.current null. Und während des Renderns von Updates wurden die DOM-Knoten noch nicht aktualisiert. Es ist also zu früh, sie zu lesen.
React setztref.currentwährend des Commits. Vor dem Aktualisieren des DOM setzt React die betroffenenref.current-Werte aufnull. Nach dem Aktualisieren des DOM setzt React sie sofort auf die entsprechenden DOM-Knoten.
Normalerweise greifst du von Event-Handlern aus auf Refs zu.Wenn du etwas mit einer Ref machen möchtest, aber kein bestimmtes Ereignis dafür vorhanden ist, benötigst du möglicherweise einen Effekt. Effekte werden auf den nächsten Seiten besprochen.
Best Practices für DOM-Manipulation mit Refs
Refs sind eine Notlösung. Sie sollten sie nur verwenden, wenn Sie "außerhalb von React" agieren müssen. Typische Beispiele hierfür sind das Verwalten des Fokus, der Scrollposition oder das Aufrufen von Browser-APIs, die React nicht bereitstellt.
Wenn Sie sich auf nicht-destruktive Aktionen wie Fokussieren und Scrollen beschränken, sollten Sie keine Probleme bekommen. Wenn Sie jedoch versuchen, das DOMmanuell zu verändern, riskieren Sie Konflikte mit den Änderungen, die React vornimmt.
Um dieses Problem zu veranschaulichen, enthält dieses Beispiel eine Willkommensnachricht und zwei Buttons. Der erste Button schaltet ihre Anzeige mithilfe vonConditional RenderingundStateum, wie man es in React normalerweise tun würde. Der zweite Button verwendet dieremove()-DOM-API, um sie gewaltsam aus dem DOM zu entfernen, außerhalb der Kontrolle von React.
Versuchen Sie, einige Male auf "Toggle with setState" zu drücken. Die Nachricht sollte verschwinden und wieder erscheinen. Drücken Sie dann auf "Remove from the DOM". Dadurch wird sie gewaltsam entfernt. Drücken Sie schließlich auf "Toggle with setState":
Nachdem Sie das DOM-Element manuell entfernt haben, führt der Versuch, es mitsetStatewieder anzuzeigen, zu einem Absturz. Das liegt daran, dass Sie das DOM geändert haben und React nicht weiß, wie es es korrekt weiter verwalten soll.
Vermeiden Sie es, von React verwaltete DOM-Knoten zu ändern.Das Ändern, Hinzufügen oder Entfernen von Kindelementen bei von React verwalteten Elementen kann zu inkonsistenten visuellen Ergebnissen oder Abstürzen wie oben führen.
Das bedeutet jedoch nicht, dass Sie es überhaupt nicht tun können. Es erfordert Vorsicht.Sie können Teile des DOM sicher ändern, die Reactkeinen Grundhat, zu aktualisieren.Wenn beispielsweise ein<div>im JSX immer leer ist, hat React keinen Grund, seine Kinderliste anzufassen. Daher ist es sicher, dort manuell Elemente hinzuzufügen oder zu entfernen.
Zusammenfassung
- Refs sind ein allgemeines Konzept, aber meistens verwenden Sie sie, um DOM-Elemente zu halten.
- Sie weisen React an, einen DOM-Knoten in
myRef.currentzu platzieren, indem Sie<div ref={myRef}>übergeben. - Normalerweise verwenden Sie Refs für nicht-destruktive Aktionen wie Fokussieren, Scrollen oder Messen von DOM-Elementen.
- Eine Komponente macht ihre DOM-Knoten standardmäßig nicht verfügbar. Sie können sich dafür entscheiden, einen DOM-Knoten verfügbar zu machen, indem Sie die
ref-Prop verwenden. - Vermeiden Sie es, von React verwaltete DOM-Knoten zu ändern.
- Wenn Sie von React verwaltete DOM-Knoten ändern, ändern Sie Teile, die React keinen Grund hat, zu aktualisieren.
Try out some challenges
Challenge 1 of 4:Play and pause the video #
In this example, the button toggles a state variable to switch between a playing and a paused state. However, in order to actually play or pause the video, toggling state is not enough. You also need to call play() and pause() on the DOM element for the <video>. Add a ref to it, and make the button work.
For an extra challenge, keep the “Play” button in sync with whether the video is playing even if the user right-clicks the video and plays it using the built-in browser media controls. You might want to listen to onPlay and onPause on the video to do that.
