Kodokon kodokon.com

useRef und DOM-Manipulation

Manipuliere das DOM und bewahre Instanzwerte mit useRef, ohne die Reinheit des Renderns zu brechen.

7 Min. · 3 Fragen

Diese Lektion in Kodokon öffnen

useRef gibt eine veränderliche Box zurück - ein Objekt mit einer einzigen current-Eigenschaft -, deren Identität jedes Rendern überlebt. Zwei grundlegende Unterschiede zum Zustand: Das Ändern von ref.current löst kein erneutes Rendern aus, und die Änderung ist sofort sichtbar, ohne auf das nächste Rendern zu warten. Daraus ergeben sich zwei Anwendungsfamilien: einen DOM-Knoten referenzieren und einen Instanzwert speichern, der Renderings überleben muss, ohne die Anzeige zu steuern.

JSX
import { useEffect, useRef } from "react";

function SearchField() {
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  return <input ref={inputRef} type="search" />;
}
React hängt den Knoten an die Ref an, nachdem das Rendern committet wurde.

Auf der Seite der Instanzwerte gehört alles, was fortbestehen muss, ohne ein Rendern auszulösen, in eine Ref: die von setInterval zurückgegebene id, die Instanz einer externen Bibliothek (eine Karte, ein Editor, ein Videoplayer) oder ein Wert aus einem vorherigen Rendern. Die goldene Regel bleibt dieselbe: Das Rendern muss eine reine Funktion von Props und Zustand sein. Refs werden in Effekten und Event-Handlern gelesen und geschrieben, nicht während des Renderns.

JAVASCRIPT
import { useEffect, useRef } from "react";

function usePrevious(value) {
  const ref = useRef(undefined);

  useEffect(() => {
    ref.current = value;
  }, [value]);

  return ref.current;
}
Der Effekt läuft nach dem Rendern: Die Ref bleibt ein Rendern zurück.

Um einen DOM-Knoten aus deiner eigenen Komponente offenzulegen, reiche die Ref weiter: Seit React 19 ist ref eine gewöhnliche Prop von Funktionskomponenten; davor war der Umweg über forwardRef Pflicht. Ein letzter Reflex, den du dir aneignen solltest: Bevorzuge den deklarativen Ansatz, wenn der Zustand ausreicht, um das Ergebnis zu beschreiben (eine CSS-Klasse, ein disabled-Attribut). Behalte Refs für das Terrain vor, das React nicht abdeckt: Fokus, Textauswahl, das Vermessen eines Elements, Scrollen, Medienwiedergabe.

JSX
import { useRef } from "react";

function TextField({ ref, ...props }) {
  return <input ref={ref} {...props} />;
}

function Form() {
  const fieldRef = useRef(null);

  return (
    <>
      <TextField ref={fieldRef} />
      <button onClick={() => fieldRef.current.focus()}>
        Give focus
      </button>
    </>
  );
}
Seit React 19 wird ref wie jede andere Prop übergeben.

Wissenscheck

Stelle sicher, dass du die wichtigsten Punkte dieser Lektion behalten hast.

  1. Welcher grundlegende Unterschied trennt useRef von useState beim Speichern eines Werts?
    • Das Ändern von ref.current löst kein erneutes Rendern aus, anders als eine Zustandsaktualisierung
    • useRef behält seinen Wert, nachdem die Komponente unmountet
    • useRef kann nur DOM-Knoten speichern
    • Refs werden zwischen allen Instanzen einer Komponente geteilt
  2. Warum auf inputRef.current in useEffect zugreifen statt während des Renderns?
    • Weil useEffect DOM-Zugriffe für bessere Performance bündelt
    • Weil Refs während des Renderns fürs Lesen gesperrt sind
    • Weil React den Knoten erst nach dem Commit anhängt: Während des ersten Renderns ist current noch null
  3. Was gibt usePrevious(value) beim allerersten Rendern zurück?
    • Den aktuellen Wert von value
    • undefined, weil der Effekt, der in die Ref schreibt, noch nicht gelaufen ist
    • null
    • Den Wert des nächsten Renderns