React 19: ref als normale Prop nutzen, ohne forwardRef
AI generated
{ }
React · React 19 · TypeScript
ref als Prop in React 19: Abschied vom forwardRef-Boilerplate
Bestehende forwardRef-Komponenten migrieren und in gemischten Codebasen kompatibel bleiben

React 19 hebt einen der aeltesten Sonderfaelle des Frameworks auf: ref laesst sich jetzt direkt als normale Prop entgegennehmen, ganz ohne forwardRef-Wrapper. Dieser Artikel zeigt das neue Muster, wie bestehende forwardRef-Komponenten migriert werden, die TypeScript-Typisierung und wie beide Muster in einer gemischten Codebasis sicher nebeneinander bestehen.

13 Min. Lesezeit React 19 refs forwardRef TypeScript Migration

1. Was sich mit React 19 bei refs geaendert hat

Bis einschliesslich React 18 war ref eine Sonderrolle unter den Props: Wer eine Funktionskomponente baute und von aussen per ref auf ein internes DOM-Element oder eine imperative Handle zugreifen wollte, musste die Komponente zwingend mit forwardRef umschliessen. Ein normaler Funktionsaufruf function MyInput(props) { ... } konnte kein ref-Prop entgegennehmen, React entfernte es intern aus den Props, bevor die Funktion ueberhaupt aufgerufen wurde.

React 19 hebt diese Einschraenkung auf: ref wird jetzt wie jeder andere Prop direkt an die Funktionskomponente durchgereicht, ganz ohne forwardRef-Wrapper. Das reduziert Boilerplate spuerbar, vereinfacht die Typisierung in TypeScript und macht Komponenten-Definitionen wieder zu einfachen Funktionen ohne Sonderfall. Fuer neue Komponenten ist forwardRef damit in aller Regel ueberfluessig geworden.

2. Das neue Muster: ref einfach als Prop entgegennehmen

Der Umstieg auf Codeebene ist unspektakulaer: ref wird einfach als weiterer Parameter in der Props-Destrukturierung aufgefuehrt, genau wie jeder andere Wert auch. Innerhalb der Komponente laesst sich der ref dann klassisch per useEffect oder direkt im JSX an ein DOM-Element weiterreichen, exakt wie man es von normalen Props gewohnt ist.

Besonders fuer kleine, wiederverwendbare UI-Bausteine wie ein Eingabefeld oder einen Button lohnt sich dieses vereinfachte Muster sofort, weil der bisherige forwardRef-Wrapper samt der zweiten Callback-Ebene komplett entfaellt. Die Komponente bleibt eine einzige, flache Funktion, was auch das Debuggen im React DevTools-Baum uebersichtlicher macht, da keine zusaetzliche ForwardRef-Ebene mehr im Komponentenbaum auftaucht.


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

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

  const focusInput = () => {
    inputRef.current?.focus();
  };

  return (
    <>
      <TextInput label="Name" ref={inputRef} />
      <button onClick={focusInput}>Fokussieren</button>
    </>
  );
}

3. Warum forwardRef ueberhaupt noetig war

Die historische Begruendung fuer forwardRef liegt in Reacts Reconciliation-Modell: ref war von Anfang an kein gewoehnlicher Datenfluss von Eltern- zu Kindkomponente, sondern ein imperativer Seitenkanal, ueber den React direkt eine DOM-Referenz oder eine Instanz zurueckmeldet. Damit dieser Seitenkanal nicht versehentlich als normaler Prop durch die Komponente durchgereicht und dabei veraendert oder ignoriert wird, entfernte React ref konsequent aus dem props-Objekt.

forwardRef gab Komponentenautoren dafuer eine explizite zweite Funktionssignatur, (props, ref) => ..., ueber die der Seitenkanal gezielt wieder zugaenglich gemacht wurde. Das funktionierte zuverlaessig, fuehrte aber dazu, dass jede wiederverwendbare Basiskomponente diesen Wrapper vorsorglich einsetzen musste, selbst wenn zum Zeitpunkt der Erstellung noch gar nicht klar war, ob ref jemals gebraucht wuerde, was in der Praxis zu viel praeventivem Boilerplate fuehrte.

4. Bestehende forwardRef-Komponenten migrieren

Die Migration einer einzelnen Komponente laeuft in drei kleinen Schritten ab: den forwardRef-Aufruf entfernen, die zweite Funktionssignatur (props, ref) zu einer flachen Props-Destrukturierung mit ref als zusaetzlichem Feld zusammenfuehren, und den Komponentennamen als normale function- oder const-Deklaration beibehalten. Der Rueckgabewert und das JSX im Komponentenkoerper bleiben dabei unveraendert, es aendert sich ausschliesslich die aeussere Funktionshuelle.

Fuer groessere Codebasen mit vielen Basiskomponenten empfiehlt sich eine schrittweise Migration Komponente fuer Komponente statt einer grossen Umbau-Aktion, weil forwardRef in React 19 weiterhin funktioniert und beide Muster problemlos nebeneinander existieren koennen. Ein guter Startpunkt sind vielgenutzte, aber einfache Komponenten wie Buttons oder Eingabefelder, bei denen sich der Aufwand pro Migration in wenigen Zeilen erschoepft.


// Vorher: React 18 Muster
const Button = forwardRef(function Button(props, ref) {
  return <button ref={ref} className="btn" {...props} />;
});

// Nachher: React 19 Muster
function Button({ ref, ...props }) {
  return <button ref={ref} className="btn" {...props} />;
}

5. Typisierung in TypeScript

Unter React 18 musste eine typisierte forwardRef-Komponente den Ref-Typ und den Props-Typ als zwei separate Generics an forwardRef uebergeben, eine Reihenfolge, die viele Entwickler regelmaessig verwechselten. Mit ref als normalem Prop reicht es, ref direkt im Props-Interface mit dem passenden Ref-Typ zu deklarieren, ueblicherweise als Ref oder als Union aus RefObject und RefCallback.

Das vereinfacht nicht nur die Signatur, sondern macht auch generische, wiederverwendbare Komponenten leichter typisierbar, weil kein separates ForwardRefExoticComponent-Konstrukt mehr um die eigentliche Komponente herum verwaltet werden muss. Bei Komponenten, die mehrere Elementtypen unterstuetzen sollen, etwa polymorphe Buttons, laesst sich der Ref-Typ zusaetzlich ueber ein generisches Typparameter an die Elementart koppeln.


import { Ref } from "react";

interface TextInputProps {
  label: string;
  ref?: Ref<HTMLInputElement>;
  placeholder?: string;
}

function TextInput({ label, ref, placeholder }: TextInputProps) {
  return (
    <label>
      {label}
      <input ref={ref} placeholder={placeholder} />
    </label>
  );
}

6. Abwaertskompatibilitaet in gemischten Codebasen

React 19 markiert forwardRef als veraltet, entfernt es aber nicht; bestehender Code, der forwardRef verwendet, laeuft weiterhin unveraendert. Das ist besonders relevant fuer Projekte, die externe UI-Bibliotheken einbinden, deren eigene Komponenten intern noch forwardRef nutzen, weil diese Bibliotheken selbst erst schrittweise auf das neue React-19-Muster umstellen werden und eine Aktualisierung nicht im eigenen Einflussbereich liegt.

In der Praxis bedeutet das, dass ein und dieselbe Codebasis ueber laengere Zeit beide Muster gleichzeitig enthalten kann, ohne dass daraus funktionale Probleme entstehen: eine mit forwardRef gebaute Komponente laesst sich problemlos innerhalb einer Komponente verwenden, die selbst bereits das neue ref-als-Prop-Muster nutzt, und umgekehrt. Ein Team kann die Migration deshalb entspannt priorisieren, statt unter Zeitdruck alle Komponenten auf einmal umzustellen.

7. Kombination mit useImperativeHandle

Komponenten, die statt eines rohen DOM-Elements eine kuratierte, imperative API nach aussen anbieten wollen, etwa nur eine focus()- und eine reset()-Methode statt des vollen input-Elements, nutzen dafuer weiterhin useImperativeHandle. Der Hook selbst hat sich funktional nicht geaendert, benoetigt aber unter React 19 kein forwardRef mehr als Traegerkomponente, sondern laesst sich direkt in einer normalen Funktionskomponente mit ref-Prop einsetzen.

Das reduziert den Boilerplate fuer imperative Komponenten-APIs auf das Noetigste: Props-Destrukturierung mit ref, ein useRef fuer das interne Element und ein useImperativeHandle-Aufruf, der die gewuenschten Methoden auf dem uebergebenen ref bereitstellt. Fuer komplexere Formularkomponenten mit mehreren imperativen Methoden bleibt dieses Muster dadurch deutlich uebersichtlicher als die zweistufige forwardRef-Variante aus React 18.


function FancyInput({ ref, ...props }) {
  const inputRef = useRef(null);

  useImperativeHandle(ref, () => ({
    focus: () => inputRef.current?.focus(),
    clear: () => {
      if (inputRef.current) inputRef.current.value = "";
    },
  }));

  return <input ref={inputRef} {...props} />;
}

8. Linting-Fallstricke und ref-Cleanup-Funktionen

Aeltere ESLint-Konfigurationen mit der react-hooks-Plugin-Regel kennen unter Umstaenden das neue ref-als-Prop-Muster noch nicht und markieren ref faelschlich als unbenutzten oder falsch platzierten Prop; ein Update auf eine aktuelle Plugin-Version behebt das zuverlaessig. Ein weiterer Stolperstein ist die Reihenfolge der Props-Destrukturierung: ref sollte nicht versehentlich Teil eines rest-Spreads werden, der ungefiltert an ein darunterliegendes Element weitergereicht wird, sonst landet ref doppelt im DOM.

React 19 fuehrt ausserdem ref-Cleanup-Funktionen ein: Ein ref-Callback kann jetzt selbst eine Funktion zurueckgeben, die beim Unmount oder bei einer ref-Aenderung automatisch aufgerufen wird, ganz analog zum bekannten useEffect-Cleanup-Muster. In Kombination mit ref als normalem Prop lassen sich dadurch Auf- und Abbau-Logik fuer ein DOM-Element, etwa das Registrieren und Entfernen eines nativen Event-Listeners, direkt und ohne zusaetzlichen useEffect am ref-Callback selbst festmachen.

9. Wann sich die Migration lohnt

Fuer neue Komponenten gibt es praktisch keinen Grund mehr, forwardRef zu verwenden, das neue Muster ist kuerzer, einfacher zu typisieren und funktional identisch. Bei bestehenden Komponenten haengt die Prioritaet davon ab, wie oft sie angefasst werden: Komponenten, die ohnehin gerade ueberarbeitet werden, lassen sich im selben Zug migrieren, waehrend stabile, selten geaenderte Komponenten ruhig mit forwardRef weiterlaufen duerfen.

Ein Laufzeit- oder Bundle-Groessen-Unterschied zwischen beiden Mustern ist praktisch nicht messbar, der Nutzen der Migration liegt ausschliesslich in Lesbarkeit, einfacherer Typisierung und weniger Boilerplate, nicht in Performance. Teams sollten die Migration deshalb als Code-Qualitaets-Massnahme behandeln, die sich gut in ohnehin geplante Refactorings einbetten laesst, statt als isolierte, dringende Aufgabe.

Aspekt forwardRef (React 18) ref als Prop (React 19) Bewertung
Boilerplate Zusaetzlicher Wrapper und zweite Signatur Normale Funktionskomponente Weniger Code in React 19
TypeScript-Typisierung forwardRef Generics ref direkt im Props-Interface Einfacher in React 19
Kompatibilitaet Funktioniert in React 18 und 19 Nur ab React 19 forwardRef noetig bei React-18-Support
useImperativeHandle Nur innerhalb forwardRef nutzbar Direkt in normaler Komponente Weniger Verschachtelung in React 19
Laufzeitverhalten Identisch Identisch Kein Performance-Unterschied

Mironsoft

React-Architektur, Performance und Magento-Frontend-Integration

React-Frontends, die schnell bleiben statt mit jedem Feature langsamer zu werden?

Wir prüfen bestehende React-Anwendungen auf unnötige Re-Renders, aufgeblähte Bundles und fragile State-Verwaltung und bauen daraus ein Frontend, das performant bleibt und sich sauber an Magento oder andere Backends anbindet.

Performance-Audit

Re-Renders, Bundle-Größe und Ladezeiten systematisch messen und beheben.

State-Architektur

Context, Zustand und Server State sauber trennen statt alles in einen Topf zu werfen.

Magento-Integration

GraphQL- oder REST-Anbindung an Magento robust und typsicher aufbauen.

10. Zusammenfassung

ref als Prop in React 19: Das Wichtigste auf einen Blick

Kernaenderung

ref wird in React 19 wie jeder andere Prop direkt an Funktionskomponenten durchgereicht, forwardRef ist optional geworden.

Migration

Wrapper entfernen, ref in die Props-Destrukturierung aufnehmen, Komponentenkoerper bleibt unveraendert.

Kompatibilitaet

forwardRef bleibt weiterhin funktionsfaehig, gemischte Codebasen mit beiden Mustern sind problemlos moeglich.

TypeScript

ref laesst sich direkt im Props-Interface typisieren, das umstaendliche forwardRef-Generics-Paar entfaellt.

11. FAQ: ref als Prop in React 19: Das Wichtigste auf einen Blick

1Muss ich forwardRef sofort aus meinem Code entfernen?
Nein, forwardRef bleibt in React 19 vollstaendig funktionsfaehig und wird nur als veraltet markiert. Eine schrittweise Migration im Rahmen ohnehin geplanter Aenderungen ist voellig ausreichend, es besteht kein akuter Handlungsdruck.
2Funktioniert ref als Prop auch in React 18?
Nein, das neue Verhalten wurde speziell in React 19 eingefuehrt. Projekte, die React 18 unterstuetzen muessen, etwa wegen einer Bibliotheksabhaengigkeit, sollten weiterhin forwardRef fuer ihre eigenen Komponenten verwenden.
3Kann ref jetzt versehentlich im rest-Spread landen und doppelt gerendert werden?
Ja, das ist ein reales Risiko, wenn ref nicht explizit aus der Destrukturierung herausgenommen wird, bevor der Rest an ein darunterliegendes Element gespreadet wird. Ref sollte deshalb immer als eigenes benanntes Feld destrukturiert werden, nicht Teil des Rest-Objekts sein.
4Wie verhaelt sich ref als Prop bei Klassenkomponenten?
Klassenkomponenten waren von der forwardRef-Notwendigkeit nie betroffen, ref auf eine Klassenkomponente verweist schon immer direkt auf die Instanz. Die React-19-Aenderung betrifft ausschliesslich Funktionskomponenten.
5Brauche ich fuer ref als Prop ein neues React-Paket oder Babel-Plugin?
Nein, es handelt sich um eine reine Laufzeitaenderung in React selbst ab Version 19, keine zusaetzlichen Build-Tools oder Plugins sind erforderlich. Ein einfaches Versions-Update von react und react-dom genuegt.
6Was passiert mit TypeScript-Typen fuer Komponenten, die React.FC verwenden?
React.FC enthielt nie automatisch ein ref-Prop, das musste schon vorher manuell ergaenzt werden. Unter React 19 laesst sich ref genauso wie jeder andere Prop einfach zum eigenen Props-Interface hinzufuegen, unabhaengig davon, ob React.FC verwendet wird oder nicht.
7Ist die Migration bei Komponenten mit mehreren Kindelementen komplizierter?
Nein, die Komplexitaet haengt nicht von der Anzahl der Kindelemente ab, sondern nur davon, wie viele verschiedene ref-Weiterleitungen innerhalb der Komponente existieren. Jede einzelne Weiterleitung wird unabhaengig migriert, unabhaengig von der restlichen JSX-Struktur.
8Kann ich in einer Komponente mehrere refs als Props entgegennehmen?
Ja, es lassen sich beliebig viele unterschiedlich benannte ref-Props definieren, etwa inputRef und containerRef, solange sie nicht ref heissen und dadurch mit dem speziellen React-Mechanismus kollidieren. Nur ein Prop namens exakt ref erhaelt die spezielle Behandlung durch React.
9Loest ref als Prop auch das Problem mit ref bei memo-umschlossenen Komponenten?
Ja, bislang musste eine memoisierte Komponente zusaetzlich mit forwardRef kombiniert werden, um ref korrekt durchzureichen. Unter React 19 reicht memo allein aus, weil ref bereits auf Ebene der zugrunde liegenden Funktionskomponente als normaler Prop ankommt.
10Gibt es einen automatisierten Codemod fuer die Migration?
Die React-Team-Empfehlung ist eine schrittweise, manuelle Migration, da sich forwardRef-Aufrufe strukturell stark unterscheiden koennen. Es existieren community-getriebene Codemod-Skripte fuer einfache Faelle, diese sollten aber vor dem Einsatz auf Testcode geprueft werden.