Referenzieren von Werten mit Refs
Wenn eine Komponente sich an Informationen "erinnern" soll, diese Informationen jedoch keineneuen Rendervorgänge auslösensollen, können Sie einenRefverwenden.
Sie werden lernen
- Wie Sie Ihrer Komponente einen Ref hinzufügen
- Wie Sie den Wert eines Refs aktualisieren
- Wie sich Refs vom State unterscheiden
- Wie Sie Refs sicher verwenden
Hinzufügen eines Refs zu Ihrer Komponente
Sie können Ihrer Komponente einen Ref hinzufügen, indem Sie denuseRef-Hook aus React importieren:
Rufen Sie innerhalb Ihrer Komponente denuseRef-Hook auf und übergeben Sie den Anfangswert, auf den Sie referenzieren möchten, als einziges Argument. Hier ist beispielsweise ein Ref für den Wert0:
useRefgibt ein Objekt wie dieses zurück:

Illustration vonRachel Lee Nabors
Sie können den aktuellen Wert dieses Refs über die Eigenschaftref.currentabrufen. Dieser Wert ist absichtlich veränderlich, das heißt, Sie können ihn sowohl lesen als auch beschreiben. Er ist wie eine geheime Tasche Ihrer Komponente, die React nicht verfolgt. (Das macht ihn zu einem "Fluchtweg" aus dem unidirektionalen Datenfluss von React – dazu später mehr!)
Hier wird ein Schaltflächenklick jedes Malref.currenterhöhen:
Der Ref verweist auf eine Zahl, aber genau wie beimStatekönnen Sie auf alles verweisen: eine Zeichenkette, ein Objekt oder sogar eine Funktion. Im Gegensatz zum State ist ein Ref ein einfaches JavaScript-Objekt mit der Eigenschaftcurrent, die Sie lesen und ändern können.
Beachten Sie, dassdie Komponente bei jeder Erhöhung nicht neu gerendert wird.Wie State werden Refs von React zwischen Neu-Renderings beibehalten. Allerdings löst das Setzen des State ein Neu-Rendering der Komponente aus. Das Ändern eines Refs tut dies nicht!
Beispiel: Bau einer Stoppuhr
Sie können Refs und State in einer einzelnen Komponente kombinieren. Lassen Sie uns beispielsweise eine Stoppuhr erstellen, die der Benutzer durch Drücken einer Schaltfläche starten oder stoppen kann. Um anzuzeigen, wie viel Zeit seit dem Drücken von "Start" vergangen ist, müssen Sie verfolgen, wann die Start-Schaltfläche gedrückt wurde und wie die aktuelle Uhrzeit ist.Diese Informationen werden für das Rendering verwendet, daher werden Sie sie im State halten:
Wenn der Benutzer "Start" drückt, verwenden SiesetInterval, um die Zeit alle 10 Millisekunden zu aktualisieren:
Wenn die Schaltfläche "Stop" gedrückt wird, müssen Sie das bestehende Intervall abbrechen, damit die Aktualisierung der State-Variablenowstoppt. Dies können Sie durch Aufruf vonclearIntervaltun, aber Sie müssen ihm die Intervall-ID übergeben, die zuvor durch densetInterval-Aufruf zurückgegeben wurde, als der Benutzer Start gedrückt hat. Sie müssen die Intervall-ID irgendwo speichern.Da die Intervall-ID nicht für das Rendering verwendet wird, können Sie sie in einem Ref halten:
Wenn eine Information zum Rendern verwendet wird, bewahren Sie sie im State auf. Wenn eine Information nur für Event-Handler benötigt wird und ihre Änderung kein erneutes Rendern erfordert, kann die Verwendung eines Refs effizienter sein.
Unterschiede zwischen Refs und State
Vielleicht denken Sie, Refs scheinen weniger „streng“ als State zu sein – Sie können sie mutieren, anstatt immer eine State-Setter-Funktion verwenden zu müssen. In den meisten Fällen sollten Sie jedoch State verwenden. Refs sind ein „Notausgang“, den Sie nicht oft benötigen. Hier ein Vergleich von State und Refs:
| Refs | State |
|---|---|
useRef(initialValue)gibt{ current: initialValue } zurück. | useState(initialValue)gibt den aktuellen Wert einer State-Variable und eine State-Setter-Funktion zurück ([value, setValue]). |
| Löst kein erneutes Rendern aus, wenn Sie ihn ändern. | Löst ein erneutes Rendern aus, wenn Sie ihn ändern. |
Veränderlich – Sie können den Wert voncurrentaußerhalb des Rendering-Prozesses ändern und aktualisieren. | „Unveränderlich“ – Sie müssen die State-Setter-Funktion verwenden, um State-Variablen zu ändern und ein erneutes Rendern in die Warteschlange zu stellen. |
Sie sollten den Wert voncurrentwährend des Renderns nicht lesen (oder schreiben). | Sie können den State jederzeit lesen. Allerdings hat jedes Rendering seinen eigenenSnapshotdes States, der sich nicht ändert. |
Hier ist eine Zähler-Schaltfläche, die mit State implementiert ist:
Weil dercount-Wert angezeigt wird, ist es sinnvoll, dafür einen State-Wert zu verwenden. Wenn der Zählerwert mitsetCount()gesetzt wird, rendert React die Komponente neu und der Bildschirm wird aktualisiert, um den neuen Zählerstand anzuzeigen.
Wenn Sie dies mit einem Ref implementieren würden, würde React die Komponente nie neu rendern, sodass Sie niemals eine Änderung des Zählerstands sehen würden! Sehen Sie, wie das Klicken auf diese Schaltflächeihren Text nicht aktualisiert:
Deshalb führt das Lesen vonref.currentwährend des Renderns zu unzuverlässigem Code. Wenn Sie das benötigen, verwenden Sie stattdessen State.
Wann man Refs verwendet
Typischerweise verwenden Sie eine Ref, wenn Ihre Komponente „aus React heraustreten“ und mit externen APIs kommunizieren muss – oft eine Browser-API, die die Darstellung der Komponente nicht beeinflusst. Hier sind einige dieser seltenen Situationen:
- Speichern vonTimeout-IDs
- Speichern und Manipulieren vonDOM-Elementen, die wir aufder nächsten Seite behandeln
- Speichern anderer Objekte, die nicht zur Berechnung des JSX notwendig sind.
Wenn Ihre Komponente einen Wert speichern muss, der aber die Renderlogik nicht beeinflusst, wählen Sie Refs.
Beste Praktiken für Refs
Die Einhaltung dieser Prinzipien macht Ihre Komponenten vorhersehbarer:
- Behandeln Sie Refs als Notausgang.Refs sind nützlich, wenn Sie mit externen Systemen oder Browser-APIs arbeiten. Wenn ein Großteil Ihrer Anwendungslogik und Ihres Datenflusses auf Refs basiert, sollten Sie Ihren Ansatz überdenken.
- Lesen oder schreiben Sie
ref.currentnicht während des Renderings.Wenn Informationen während des Renderings benötigt werden, verwenden SieState. Da React nicht weiß, wann sichref.currentändert, macht selbst das Lesen während des Renderings das Verhalten Ihrer Komponente schwer vorhersehbar. (Die einzige Ausnahme davon ist Code wieif (!ref.current) ref.current = new Thing(), der die Ref nur einmal während des ersten Renderings setzt.)
Die Einschränkungen von React State gelten nicht für Refs. State verhält sich beispielsweise wie einSnapshot für jedes Renderingundaktualisiert sich nicht synchron.Wenn Sie jedoch den aktuellen Wert einer Ref mutieren, ändert er sich sofort:
Das liegt daran, dassdie Ref selbst ein reguläres JavaScript-Objekt ist,und sich dementsprechend verhält.
Sie müssen sich auch keine Gedanken über dasVermeiden von Mutationenmachen, wenn Sie mit einer Ref arbeiten. Solange das Objekt, das Sie mutieren, nicht zum Rendern verwendet wird, kümmert es React nicht, was Sie mit der Ref oder ihrem Inhalt machen.
Refs und das DOM
Sie können eine Ref auf jeden Wert verweisen lassen. Der häufigste Anwendungsfall für eine Ref ist jedoch der Zugriff auf ein DOM-Element. Das ist beispielsweise praktisch, wenn Sie einen Input programmatisch fokussieren möchten. Wenn Sie ein Ref-Attribut in JSX eine Ref übergeben, wie<div ref={myRef}>, setzt React das entsprechende DOM-Element inmyRef.current. Sobald das Element aus dem DOM entfernt wird, aktualisiert ReactmyRef.current auf null. Sie können mehr darüber inManipulieren des DOM mit Refs lesen.
Zusammenfassung
- Refs sind eine Notluke, um Werte festzuhalten, die nicht für das Rendering verwendet werden. Sie werden sie nicht oft brauchen.
- Ein Ref ist ein einfaches JavaScript-Objekt mit einer einzigen Eigenschaft namens
current, die Sie lesen oder setzen können. - Sie können React bitten, Ihnen ein Ref zu geben, indem Sie den
useRef-Hook aufrufen. - Wie State ermöglichen Refs es Ihnen, Informationen zwischen erneuten Renderings einer Komponente beizubehalten.
- Anders als beim State löst das Setzen des Werts
currenteines Refs kein erneutes Rendering aus. - Lesen oder schreiben Sie
ref.currentnicht während des Renderings. Dies macht Ihre Komponente schwer vorhersehbar.
Probieren Sie einige Herausforderungen aus
Challenge 1 of 4:Einen defekten Chat-Eingang reparieren #
Geben Sie eine Nachricht ein und klicken Sie auf „Senden“. Sie werden feststellen, dass es eine Verzögerung von drei Sekunden gibt, bevor die „Gesendet!“-Meldung erscheint. Während dieser Verzögerung sehen Sie einen „Rückgängig“-Button. Klicken Sie darauf. Dieser „Rückgängig“-Button soll verhindern, dass die „Gesendet!“-Meldung erscheint. Er tut dies, indem er clearTimeout für die Timeout-ID aufruft, die während handleSend gespeichert wurde. Allerdings erscheint die „Gesendet!“-Meldung weiterhin, selbst nachdem „Rückgängig“ geklickt wurde. Finden Sie heraus, warum es nicht funktioniert, und beheben Sie das Problem.
