forwardRef ist eine React-API, die eine Function-Component wickelt und ihr erlaubt, eine ref aus dem Eltern-Aufruf zu empfangen und weiterzureichen. Ohne forwardRef ist die ref-Prop bei Function-Components stumm — React warnt sogar in DevMode. Mit forwardRef wird die Komponente zur „Brücke" und kann die ref an ein internes DOM-Element binden. Wichtig: ab React 19 ist ref eine ganz normale Prop, und forwardRef wird obsolet. Wer auf React 19 setzt, kann direkt ref={...} an Custom-Components übergeben, ohne Wrapper.

Das Problem ohne forwardRef

Bei nativen DOM-Elementen funktioniert ref direkt. Bei eigenen Function-Components nicht — React warnt:

TypeScript ProblemOhneForwardRef.jsx
function FancyInput(props) {
    return <input className="fancy" {...props} />;
}

function Form() {
    const inputRef = useRef(null);
    return <FancyInput ref={inputRef} />;
    // Warning: Function components cannot be given refs.
}

inputRef.current bleibt null. Die ref-Prop wird nicht an das innere <input> weitergereicht.

Lösung mit forwardRef (React 16.3 – 18)

forwardRef wickelt die Komponente und macht den zweiten Parameter ref verfügbar:

TypeScript FancyInput.jsx
import { forwardRef, useRef } from 'react';

const FancyInput = forwardRef(function FancyInput(props, ref) {
    return <input className="fancy" ref={ref} {...props} />;
});

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

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

    return (
        <>
            <FancyInput ref={inputRef} />
            <button onClick={handleFocus}>Fokussieren</button>
        </>
    );
}

Jetzt zeigt inputRef.current auf das innere <input>-DOM-Element. focus() funktioniert.

Mit TypeScript

TypeScript FancyInput.tsx
import { forwardRef, useRef } from 'react';

type FancyInputProps = {
    placeholder?: string;
};

const FancyInput = forwardRef<HTMLInputElement, FancyInputProps>(
    function FancyInput(props, ref) {
        return <input className="fancy" ref={ref} {...props} />;
    }
);

function Form() {
    const inputRef = useRef<HTMLInputElement>(null);
    // inputRef.current ist HTMLInputElement | null
    return <FancyInput ref={inputRef} placeholder="Name" />;
}

Generische Typen: erst der Element-Typ (worauf zeigt die ref?), dann der Props-Typ.

React 19 — ref als normale Prop

Ab React 19 ist forwardRef obsolet. Components empfangen ref direkt als Prop:

TypeScript React19.jsx
// React 19+ — kein forwardRef nötig
function FancyInput({ ref, ...props }) {
    return <input className="fancy" ref={ref} {...props} />;
}

function Form() {
    const inputRef = useRef(null);
    return <FancyInput ref={inputRef} placeholder="Name" />;
}

Vorteile:

  • Keine Doppel-Funktion-Wrapping (forwardRef(function ...)).
  • TypeScript-Typing einfacher (ref ist nur eine Prop).
  • Konsistenter mit anderen Props.

Migration: einfach forwardRef(...) entfernen und ref zum Props-Destructuring hinzufügen. React-19-Linter helfen dabei.

Mit useImperativeHandle kombinieren

Wenn man nicht das innere DOM-Element nach außen geben will, sondern ein eigenes API (z.B. nur focus() und clear()), kombiniert man forwardRef mit useImperativeHandle:

TypeScript CustomAPI.jsx
import { forwardRef, useImperativeHandle, useRef } from 'react';

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

    useImperativeHandle(ref, () => ({
        focus: () => inputRef.current.focus(),
        clear: () => { inputRef.current.value = ''; },
    }), []);

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

function Form() {
    const fancyRef = useRef(null);
    return (
        <>
            <FancyInput ref={fancyRef} />
            <button onClick={() => fancyRef.current.focus()}>Fokus</button>
            <button onClick={() => fancyRef.current.clear()}>Leeren</button>
        </>
    );
}

fancyRef.current hat dann nur die Methoden focus und clear — nicht das ganze DOM-Element. Sauberere API, weniger Coupling.

displayName für DevTools

forwardRef-Components zeigen in React DevTools per Default als „ForwardRef" an. Mit displayName lässt sich das anpassen:

TypeScript displayName.jsx
const FancyInput = forwardRef(function FancyInput(props, ref) {
    return <input ref={ref} {...props} />;
});

FancyInput.displayName = 'FancyInput';

In React 19 ist das unnötig — die Komponente hat ohnehin ihren Funktions-Namen.

Besonderheiten

forwardRef ist bis React 18 Pflicht für Component-Refs.

Ohne forwardRef wird die ref-Prop einer Function-Component IGNORIERT — React warnt im Dev-Mode. forwardRef macht ref zum zweiten Parameter der Komponenten-Funktion.

React 19: ref ist eine normale Prop — `forwardRef` obsolet.

Ab React 19 kann jede Function-Component ref direkt aus den Props nehmen. forwardRef bleibt rückwärtskompatibel, ist aber für neuen Code unnötig. Linter erkennen und schlagen die Migration vor.

forwardRef-Component-Signatur: `(props, ref)` statt nur `props`.

Anders als normale Function-Components hat die mit forwardRef gewickelte Funktion ZWEI Parameter. Erst props, dann ref. Beim Destructuring beider muss man das beachten.

ref-Forwarding ans innere Element: `ref={ref}` an den DOM-Knoten.

Innerhalb der gewickelten Komponente muss die empfangene ref an ein echtes DOM-Element (oder eine andere forwardRef-Komponente) weitergegeben werden, damit sie etwas „zeigt". Sonst bleibt sie null.

useImperativeHandle für selektives Component-API.

Statt das ganze DOM nach außen zu geben, exposed man nur ausgewählte Methoden. Klare API, weniger Coupling. Details im useImperativeHandle-Artikel.

TypeScript-Generic: forwardRef.

Erst der Element-Typ (worauf zeigt die ref im Element-Sinn?), dann der Props-Typ. forwardRef<HTMLInputElement, MyInputProps>. In React 19 wird ref typmäßig zu einer normalen Prop und vereinfacht das.

displayName für lesbarere DevTools (pre-React-19).

forwardRef-Components zeigen sich als „ForwardRef" oder „ForwardRef(MyComponent)" in DevTools. MyComponent.displayName = 'MyComponent' macht das sauberer. In React 19 unnötig.

forwardRef NICHT für jeden Component-Use-Case.

Wenn die Komponente nicht imperative gesteuert werden muss (focus, scroll, externes API), braucht sie keine ref. Reine Display-Komponenten brauchen kein forwardRef. Faustregel: erst Bedarf prüfen, dann wrappen.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Refs

Zur Übersicht