useRef ist ein React-Hook, der ein mutierbares ref-Objekt mit einer .current-Eigenschaft erstellt, das zwischen Komponenten-Renderings erhalten bleibt. Im Gegensatz zu useState löst eine Änderung von .current kein Neurendern aus, was useRef ideal zum Speichern von DOM-Referenzen, Timern und beliebigen Werten macht, die Renderings ohne UI-Neurendern überdauern müssen. Laut React-Dokumentation (2025) wird das ref-Objekt einmal während der Lebensdauer der Komponente erstellt und ändert sich nicht zwischen Renderings, was Referenzstabilität garantiert.
Wichtige Punkte
useRef ist ein in React 16.8 eingeführter Hook, der ein mutierbares ref-Objekt mit einer einzigen .current-Eigenschaft zurückgibt. Der Anfangswert wird beim Mounten der Komponente .current zugewiesen. Der Hauptunterschied zu einer normalen Variable besteht darin, dass das ref-Objekt Neurenderungen überlebt: Bei nachfolgenden Renderings erstellt React das ref nicht neu, sondern gibt dasselbe Objekt zurück.
Intern verwendet useRef denselben Mechanismus wie useState und useEffect — eine verkettete Liste von Hooks auf dem Fiber-Knoten. Im Gegensatz zu useState verfolgt React jedoch keine Änderungen am ref-Objekt, stellt keine Aktualisierungen in die Warteschlange und plant kein Neurendern. Dies macht useRef zu einem äußerst leichten Hook, der die Leistung selbst bei häufigen Änderungen nicht beeinträchtigt.
Laut React-Team — Hooks FAQ (2025) ist useRef im Wesentlichen eine „Box“, die einen Wert speichert. Syntaktischer Zucker: const ref = useRef(initialValue) ist äquivalent zu const ref = { current: initialValue } mit dem Unterschied, dass React garantiert, dass das ref-Objekt bei jedem Rendern dasselbe ist. Keine Magie — nur eine stabile Referenz, die von React verwaltet wird.
import { useRef } from 'react';
function Component() {
const countRef = useRef(0);
// countRef.current = 0 anfangs
// countRef.current = 5 nach Mutation
// Kein Neurendern erfolgt!
}
Der häufigste Anwendungsfall für useRef ist der direkte Zugriff auf ein DOM-Element. React weist elementRef.current nach dem Mounten der Komponente eine Referenz auf den DOM-Knoten zu. Dies ist erforderlich, um ein Input zu fokussieren, Elementabmessungen zu messen, mit Animationsbibliotheken und Bibliotheken zu integrieren, die kein React-Rendering verwenden.
React verwaltet automatisch ref-Referenzen auf das DOM: Beim Mounten wird der tatsächliche DOM-Knoten zugewiesen, beim Unmounten auf null gesetzt. Dies stellt sicher, dass .current immer den aktuellen Wert enthält, und verhindert Speicherlecks durch hängende Referenzen auf entfernte Elemente. Keine manuelle Bereinigung erforderlich.
function AutoFocusInput() {
const inputRef = useRef(null);
useEffect(() => {
// Input nach dem Mounten der Komponente fokussieren
inputRef.current?.focus();
}, []);
return <input ref={inputRef} type="text" />;
}
Laut React — Refs and DOM-Dokumentation (2025) verwenden Sie ref nicht für deklarative Operationen — Öffnen/Schließen von Modals, Verwalten der Sichtbarkeit. Für diese Zwecke gibt es state und Props. Refs sind für imperative Operationen gedacht, die nicht deklarativ ausgedrückt werden können: Fokus, Textauswahl, Integration mit Bibliotheken von Drittanbietern.
Der zweitwichtigste Anwendungsfall ist das Speichern beliebiger Werte, die zwischen Renderings erhalten bleiben müssen, deren Änderungen jedoch kein Neurendern auslösen sollen. Typische Beispiele: Timer-Kennungen (setInterval/setTimeout), Abbruch-Flags für Anfragen, vorherige Prop-Werte zum Vergleich und alle Daten, die die UI-Ausgabe nicht beeinflussen.
Dies ist besonders nützlich in useEffect: useRef speichert die Timer-Kennung und die Bereinigung löscht sie. Wenn timerId in useState gespeichert wäre, würde jeder setTimerId-Aufruf ein unnötiges Neurendern verursachen, das weder für die Logik noch für die UI benötigt wird. useRef löst dieses Problem ohne Overhead und ohne unnötiges Neurendern.
function Timer() {
const intervalRef = useRef(null);
const start = () => {
intervalRef.current = setInterval(() => {
console.log('Tick');
}, 1000);
};
const stop = () => {
clearInterval(intervalRef.current);
};
useEffect(() => stop, []);
return <><button onClick={start}>Start</button><button onClick={stop}>Stop</button></>;
}
Das Hauptdilemma — die Wahl zwischen useRef und useState — wird durch eine Frage gelöst: „Ist bei Wertänderung ein Neurendern erforderlich?“. Wenn ja — useState. Wenn nein — useRef. useState speichert den Zustand, der die Komponentenausgabe beeinflusst; useRef speichert Daten, die für die interne Logik benötigt werden, aber die UI nicht beeinflussen.
In der Praxis verwenden Entwickler useRef häufig zum Speichern von Callbacks, um Probleme mit Closures zu vermeiden. Wenn useEffect beispielsweise ein Ereignis abonniert und der Callback den aktuellen Zustand benötigt — speichern Sie den Callback in useRef. Aktualisieren Sie bei jedem Rendern ref.current mit einer neuen Funktion, und der Effekt ruft immer den aktuellen Callback ohne erneutes Abonnieren auf.
| Kriterium | useRef | useState |
|---|---|---|
| Neurendern | Löst bei Änderung nicht aus | Löst bei jedem setState aus |
| Mutation | Direkt: ref.current = Wert | Über Setter: setState(Wert) |
| Verwendung in JSX | Nicht verwendet (kein Effekt) | In der Komponentenausgabe verwendet |
| Beispiel | Timer, DOM-Referenzen, vorherige Werte | Formulardaten, UI-Zustand, Flags |
Es gibt ein Anti-Pattern: useRef für Daten zu verwenden, die in JSX benötigt werden, deren Änderungen jedoch kein Neurendern auslösen sollen. Dies führt zu einer Desynchronisation — die UI zeigt alte Daten, während ref.current bereits neu ist. Wenn der Wert in der UI angezeigt wird — verwenden Sie useState. Wenn er nur intern verwendet wird — useRef.
Die Kombination useRef + useEffect ist das Standardmuster zum Verfolgen vorheriger Prop-Werte. Speichern Sie den vorherigen Wert in ref, vergleichen Sie ihn mit dem aktuellen Wert in useEffect und treffen Sie Entscheidungen basierend auf der Differenz. Dies ist besonders nützlich bei Animationen, wenn Sie wissen müssen, welchen Wert vor der Änderung hatte.
function PriceDisplay({ price }) {
const prevPriceRef = useRef(price);
useEffect(() => {
const prevPrice = prevPriceRef.current;
if (price > prevPrice) {
animateUp();
} else if (price < prevPrice) {
animateDown();
}
prevPriceRef.current = price;
}, [price]);
return <span>${price}</span>;
}
Laut React-Dokumentation — Hooks FAQ (2025) wird dieses Muster als „Previous Value Pattern“ bezeichnet. Es funktioniert, weil useRef den Wert zwischen Renderings beibehält und useEffect nach der Bestätigung der Änderungen ausgeführt wird. Zunächst wird das DOM mit dem neuen price aktualisiert, dann vergleicht useEffect ihn mit dem vorherigen (noch in ref) und aktualisiert ref.current auf den aktuellen Wert.
Der häufigste Fehler ist das Lesen von ref.current während der Render-Phase, um JSX zu berechnen. Da das Ändern von ref.current kein Neurendern auslöst, kann die Komponente einen veralteten Wert verwenden. Wenn .current an der UI-Ausgabe beteiligt ist — verwenden Sie useState. Wenn Sie ref und state synchronisieren müssen, verwenden Sie useEffect, um den state aus ref zu aktualisieren.
// ❌ ref.current während des Renderings nicht zum Anzeigen lesen
function BadComponent() {
const valRef = useRef(0);
return <p>{valRef.current}</p>; // wird bei Mutation NICHT aktualisiert
}
// ✅ State zum Anzeigen, ref für Logik verwenden
function GoodComponent() {
const [val, setVal] = useState(0);
const valRef = useRef(0);
return <p>{val}</p>;
}
Ein weiterer häufiger Fehler ist die Verwendung von useRef als einzige Methode zum Speichern des Zustands in einer Komponente, wenn die Daten tatsächlich die UI beeinflussen. Entwickler wählen useRef, um „unnötiges“ Neurendern zu vermeiden, erhalten aber letztendlich eine UI, die nicht aktualisiert wird. Der richtige Ansatz: Verwenden Sie useState für UI-Daten und useRef nur für Hilfswerte, die nicht am Rendering beteiligt sind.
Häufig gestellte Fragen
Ja, dies ist ein gängiges Muster — das Previous-State-Pattern. Erstellen Sie ein ref und aktualisieren Sie es in useEffect bei jeder Änderung des verfolgten Werts. Zwischen dem Rendern und dem Effekt enthält ref.current den vorherigen Wert, der mit dem aktuellen verglichen werden kann. Dies erfordert keine zusätzlichen Neurenderungen und funktioniert mit jedem Datentyp.
React weist ref.current den Wert des DOM-Knotens erst zu, nachdem das Element gerendert und zum tatsächlichen DOM hinzugefügt wurde. Während des ersten Renderings ist die Komponente noch nicht gemountet, daher ist ref.current gleich dem Anfangswert (null). Der Zugriff auf das DOM über ref.current ist nur in useEffect oder in Ereignishandlern möglich, die nach dem Mounten aufgerufen werden.
createRef erstellt bei jedem Rendern ein neues ref-Objekt — es sollte nur in Klassenkomponenten verwendet werden. useRef erstellt das ref einmal und gibt bei allen nachfolgenden Renderings dasselbe Objekt zurück. In funktionalen Komponenten verwenden Sie ausschließlich useRef; createRef führt bei Neurendern zu Wertverlust, da das Objekt neu erstellt wird.
Ja, ein ref-Objekt kann als normale Prop übergeben werden: <Child inputRef={inputRef} />. Die Kindkomponente verwendet es über inputRef.current. Um ein ref jedoch direkt an das DOM-Element einer Kindkomponente zu übergeben, verwenden Sie forwardRef — einen HOC, der das Durchreichen von refs über Props ermöglicht. Ohne forwardRef wird das ref nicht automatisch an das DOM-Element innerhalb der Kindkomponente gebunden.
Binden Sie ein ref an das Element, lesen Sie dann in useEffect ref.current.getBoundingClientRect() oder ref.current.offsetWidth / offsetHeight. Für die reaktive Verfolgung von Größenänderungen verwenden Sie ResizeObserver innerhalb von useEffect: Erstellen Sie einen Observer, abonnieren Sie Änderungen und aktualisieren Sie den state mit den neuen Abmessungen. Vergessen Sie nicht, den Observer im Cleanup zu trennen.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch