What is `forwardRef()` in React used for?
TL;DR
As of React 19 (December 2024), forwardRef() is no longer necessary, function components can now accept ref as a regular prop, so wrapping in forwardRef() is no longer required. React plans to deprecate forwardRef() in a future release. forwardRef() historically existed because, before React 19, function components could not receive a ref prop and forwardRef() was the official workaround for forwarding a parent's ref down to a child DOM node or component.
forwardRef historically let a function component receive a parent's ref and forward it to a child, while React 19 permits ref as a regular prop.
The modern answer (React 19+)
In React 19, ref is just a regular prop on function components. You can destructure it like any other prop and pass it through to a DOM element or child component. There is no longer any reason to reach for forwardRef() in new code:
forwardRef() itself still works in React 19.2. The React documentation marks it as no longer necessary and says it will be deprecated in a future release, so migrations can be gradual and should account for the React versions supported by the application or library.
Why forwardRef() existed (legacy context)
Before React 19, ref was a "magic" prop that React intercepted, passing ref to a function component did nothing useful. forwardRef() was the API React provided to opt a function component into receiving a ref alongside its props, so the parent could reach a specific DOM node inside it (e.g. focus an input, measure a node, integrate with imperative third-party libraries).
useImperativeHandle
When you want to expose a custom imperative API to the parent (rather than the raw DOM node), pair ref with useImperativeHandle. This is unchanged in React 19, only the ref-forwarding mechanism has changed.
The parent now sees { focus, clear } on the ref instead of the underlying input element. Use this sparingly: it is an escape hatch out of the declarative model.
Things to keep in mind
Ref forwarding exposes an imperative relationship, so its target and version requirements should remain explicit:
- Class components: A
refattached to a class component receives the class instance directly. They have never neededforwardRef(), and that is unchanged. - Forward to a DOM node or imperative handle: A ref must ultimately be attached to a DOM element, a class instance, or an object returned from
useImperativeHandle. Forwarding it to another function component just makes that component the new owner of the ref prop. - Migration: If you maintain a library that ships
forwardRef-wrapped components, dropping the wrapper requires a peer-dependency bump to React 19. Many libraries currently ship both forms during the transition.
Further reading
- React documentation on
forwardRef()(legacy) - React 19 release notes —
refas a prop - Using the
useRefHook useImperativeHandle- Manipulating the DOM with refs