Der React-Hook useRef wird oft ausschließlich mit dem direkten Zugriff auf DOM-Elemente in Verbindung gebracht. Dabei bietet useRef weit mehr Potenzial: Es ermöglicht die Persistenz von veränderlichen Werten über Renderzyklen hinweg, ohne ein erneutes Rendern der Komponente auszulösen. Dadurch eignet sich useRef hervorragend für das Speichern von Instanzvariablen, Timeout-IDs, vorherigen Props oder State-Werten sowie für die Implementierung imperativer Logiken innerhalb funktionaler Komponenten. Diese vielseitigen Anwendungsmöglichkeiten machen useRef zu einem essenziellen Werkzeug für komplexe State- und Lifecycle-Optimierungen in React.
Einleitung
Zugriff auf DOM-Elemente mit useRef() ist eine der häufigsten Verwendungsmöglichkeiten. Es gibt allerdings noch einige weitere. In einem Ref-Objekt kann man so gut wie alle Typen von Werten speichern.
Man kann ein Ref-Objekt erstellen und zu jeder Zeit den Wert auslesen oder ändern innerhalb der Komponente, zu welcher dieses Objekt gehört.
Wichtig
Der Wert des Ref-Objekts ändert sich nicht während der Lebenszeit eines Components. Dieser bleibt erhalten, auch wenn ein Component aufgrund von Änderungen neuinitialisiert wird.
Somit kann man useRef() verwenden, wenn man bestimmte Informationen oder gespeicherte Daten bei Reinitialisierung des Components erhalten möchte.
Referenz und Zustand
Es gibt bestimmte Unterschiede zwischen Referenzen (useRef()) und Zustandverwaltung (useState()), auch, wenn beide bestimmte Werte speichern können. Dieser Unterschied ist wichtig, damit man korrekt diese Funktionen und daraus resultierende Objekt sinnvoll und korrekt einsetzt.
Betrachten wir ein Beispiel, bei dem wir ein paar Werte auf unterschiedliche Arten speichern.
In diesem Beispiel definieren wir folgende Variablen:
counterState: Definiert über State (useState())counterRef: Definiert über Referenzen (useRef())counterVariable: Definiert klassisch als Variable
import { useRef, useState } from 'react';
function UseRefExampleOne() {
const [counterState, setCounterState] = useState(0);
const counterRef = useRef(0);
let counterVariable = 0;
const handleUpdateCounters = () => {
setCounterState(1);
counterRef.current = 1;
counterVariable = 1;
};
return (
<>
<button onClick={handleUpdateCounters}>
Update counters
</button>
<hr />
<ul>
<li>Counter state: {counterState}</li>
<li>Counter ref: {counterRef.current}</li>
<li>Counter variable: {counterVariable}</li>
</ul>
</>
);
}Beim Klick auf den Button "Update counters" werden nun zwei von drei Variablen aktualisiert.
Die Variable counterVariable wurde in der Funktion handleUpdateCounters() in Wirklichkeit aktualisiert. Es gibt jedoch keine Reflektion in UI dafür. Der Grund dafür ist, dass nach Reinitialisierung des Components, ausgelöst durch die State-Änderung, eine neue counterVariable Variable wurde erzeugt.
Der Wert in counterRef bleibt hingegen bei 1 bestehen. Eine Neu-Ausführung des Component-Codes ändert der Wert eine Ref-Variable nicht.
- [✅]:
counterState - [✅]:
counterRef - [❌]:
counterVariable

Wir verändern nun unser Beispiel und lassen State vollständig weg. Es wird nur mit Refs gearbeitet.
import { useRef } from 'react';
const UseRefExampleTwo = () => {
const counterRefOne = useRef(0);
const counterRefTwo = useRef(0);
let counterVariable = 0;
const handleUpdateCounters = () => {
counterRefOne.current = 1;
counterRefTwo.current = 1;
counterVariable = 1;
console.log('Counter ref one:', counterRefOne.current);
console.log('Counter ref two:', counterRefTwo.current);
console.log('Counter variable:', counterVariable);
};
return (
<>
<button onClick={handleUpdateCounters}>
Update counters
</button>
<hr/>
<ul>
<li>Counter ref one: {counterRefOne.current}</li>
<li>Counter ref two: {counterRefTwo.current}</li>
<li>Counter variable: {counterVariable}</li>
</ul>
</>
);
};
export default UseRefExampleTwo;Beim Klick nun auf den Button "Update counters" wird sich in der UI nichts verändern, weil keine Aktualisierung durch eine Zustandsänderung ausgelöst wurde.
Wichtig: Änderungen der Ref-Werte lösen keine Reinitialisierung des Components aus.

Referenzen auf Components
Man kann Referenzen nicht nur auf DOM-Elemente setzen. Es ist ebenfalls möglich damit Zugriff auf andere Components zu erhalten.
Lasst uns wieder ein Beispiel anschauen, bestehend aus zwei Parts. Stellen wir uns vor, wir haben ein Formular-Component, welches bestimmte Bestandteile als gesonderte, eigenständige Components einbindet (verwendet). In so einem Fall würden wir vor der Aufgabe stehen, an die Daten aus diesen Components heran zu kommen, wenn wir das Formular absenden und die Daten weiterverarbeiten möchten. Oder, wenn wir diese Elemente nach einem Submit-Event zurücksetzen wollen. Auch hier benötigen wir eine Brücke bzw. eine Lösung.
Der erste Part unseren Beispiels zeigt und die Grundstruktur auf, die uns vor diesem Problem stellt.
import { useState } from 'react';
function CheckboxOptions() {
const [checkboxOne, setCheckboxOne] = useState(false);
const [checkboxTwo, setCheckboxTwo] = useState(false);
function handleUpdateCheckboxOne() {
setCheckboxOne(prevState => !prevState);
}
function handleUpdateCheckboxTwo() {
setCheckboxTwo(prevState => !prevState);
}
return (
<div className="form_field checkbox_wrapper">
<label>
<input
type="checkbox"
id="fieldCheckboxOne"
checked={checkboxOne}
onChange={handleUpdateCheckboxOne}
/>
<span>Checkbox one</span>
</label>
<label>
<input
type="checkbox"
id="fieldCheckboxTwo"
checked={checkboxTwo}
onChange={handleUpdateCheckboxTwo}
/>
<span>Checkbox two</span>
</label>
</div>
);
}
function FormComponent() {
function handleSubmitForm(event) {
event.preventDefault();
}
return (
<form onSubmit={handleSubmitForm}>
<div className="form_field">
<label htmlFor="fieldUsername">Username</label>
<input type="text" id="fieldUsername" name="fieldUsername" />
</div>
<CheckboxOptions />
<div className="form_actions">
<button>Submit</button>
</div>
</form>
);
}
export default FormComponent;Wie wir an diesem Beispiel sehen können, ist es zunächst nicht ohne Weiteres möglich an die Daten aus dem Component CheckboxOptions heran zu kommen, um diese in der handleSubmitForm() Funktion zu verwenden.
An dieser Stelle können Refs hilfreich sein. Man kann mit ihrer Hilfe auf bestimmte Werte oder Funktionen aus anderen Components zugreifen. Sie bilden eine Art Kommunikationsbrücke zwischen zwei Components.
Man kann Referenz auf ein Component mittels Props empfangen. Das Schema würde dabei wie folgt aussehen.
function SideComponent(props) {
// ...
}
export default SideComponent;Und im Component mit der Definition der Referenz.
function MainComponent() {
const refSideComponent = useRef(null);
return <SideComponent ref={refSideComponent} />;
}Diese Verwendungsart funktioniert allerdings erst seit React 19. Vor React 18 müsste man die forwardRef() Funktion verwenden, als eine Art Wrapper verwenden.
Standardmäßig erhalten Components immer props als Parameter. Durch die Verwendung der forwardRef() Funktion erhalten die Components nun zwei, statt einem, Parameter.
Vor React 19 würde das Verwendungsschema wie folgt aussehen.
function SideComponent(props, ref) {}
export default SideComponent;Und im Component mit der Erzeugung des Referenzobjekts.
function MainComponent() {
const refSideComponent = useRef({});
return <SideComponent ref={refSideComponent} />;
}Nun bauen wir unser oberes Beispiel so um, dass wir eine Referenz auf das Component CheckboxOptions erhalten.
import { useState, useRef } from 'react';
function CheckboxOptions(props) {
// Wir entpacken 'ref' aus 'props'
const { ref } = props;
const [checkboxOne, setCheckboxOne] = useState(false);
const [checkboxTwo, setCheckboxTwo] = useState(false);
function handleUpdateCheckboxOne() {
setCheckboxOne(prevState => !prevState);
}
function handleUpdateCheckboxTwo() {
setCheckboxTwo(prevState => !prevState);
}
// Neue Funktion zum Zurücksetzen
function resetCheckboxes() {
setCheckboxOne(false);
setCheckboxTwo(false);
}
// Aufbau des ref-Objekts (initial war leer)
ref.current.resetCheckboxes = resetCheckboxes;
ref.current.selectedCheckboxes = {
checkboxOne: checkboxOne,
checkboxTwo: checkboxTwo
};
return (
<div className="form_field checkbox_wrapper">
<label>
<input
type="checkbox"
id="fieldCheckboxOne"
checked={checkboxOne}
onChange={handleUpdateCheckboxOne}
/>
<span>Checkbox one</span>
</label>
<label>
<input
type="checkbox"
id="fieldCheckboxTwo"
checked={checkboxTwo}
onChange={handleUpdateCheckboxTwo}
/>
<span>Checkbox two</span>
</label>
</div>
);
}
function FormComponent() {
// Ref-Objekt - initial leer
const refCheckboxOptions = useRef({});
function handleSubmitForm(event) {
event.preventDefault();
// Ausgabe von ausgewählten Checkboxen
console.log(refCheckboxOptions.current.selectedCheckboxes);
// Aufruf der Funktion zum Zurücksetzen
refCheckboxOptions.current.resetCheckboxes();
}
return (
<form onSubmit={handleSubmitForm}>
<div className="form_field">
<label htmlFor="fieldUsername">Username</label>
<input type="text" id="fieldUsername" name="fieldUsername" />
</div>
<CheckboxOptions ref={refCheckboxOptions} />
<div className="form_actions">
<button>Submit</button>
</div>
</form>
);
}
export default FormComponent;
Besonderheiten
useRef als Mutable Container — Hauptanwendung jenseits von DOM.
Timer-IDs (setInterval/setTimeout), Promise-Cancel-Flags, externe Library-Instanzen, vorherige Werte. Alles, was sich „nebenbei" ändert, ohne dass die UI das wissen muss.
usePrevious: Klassisches Custom-Hook-Pattern mit Ref.
const ref = useRef(); useEffect(() => { ref.current = value; }); return ref.current — speichert den Wert NACH dem Render, gibt aktuellen Wert ZURÜCK (= vorheriger im Vergleich zu State).
Refs für Component-Kommunikation seit React 19 ohne forwardRef.
Pre-19: forwardRef-Wrapper nötig, sonst kommt ref nicht durch. Ab React 19: ref ist eine normale Prop, kein Wrapper mehr. Pre-19-Code: forwardRef bleibt funktional.
useImperativeHandle für selektive API nach außen.
Eltern-Component soll nur bestimmte Methoden des Kindes aufrufen können (focus, scroll, reset) — nicht das gesamte DOM-Element. useImperativeHandle ist das Werkzeug, der eigene API über die ref exposes.
Ref-Zuweisung in useEffect: `ref.current` ist DOM ab dem ersten Effect-Lauf.
useEffect(() => { ref.current.focus() }, []) ist sicher — der Effect läuft nach dem ersten Mount. Im Component-Body direkt ist ref.current beim ersten Render noch null.
setTimeout-IDs in Ref speichern für Cleanup.
const id = setTimeout(...); ref.current = id; bewahrt die ID zwischen Renders. Im Cleanup: clearTimeout(ref.current). So überleben Timer Re-Renders ohne globale Variable.
Refs sind pro Komponenten-Instanz — kein Sharing.
Zwei <MyComponent />-Instanzen haben getrennte useRef-Werte. Für „global geteilte" Werte: Context oder externe Stores.
Refs ändern niemals — IMMER dasselbe Wrapper-Objekt.
const ref = useRef(0) liefert über alle Renders DASSELBE {current: 0}-Objekt. Nur ref.current kann sich ändern. Daher: ref-Objekt in Dependency-Arrays ist nutzlos.
Weiterführende Ressourcen
Externe Quellen
- useRef – react.dev
- Manipulating the DOM with Refs – react.dev
- forwardRef – react.dev
- useImperativeHandle – react.dev