React 20 `ref` as a Prop: Migrating Away From `forwardRef` Across a Large Component Library React 20 treats ref as a standard prop, eliminating the need for forwardRef wrappers. Component library teams face a migration path that requires careful planning across versioning, TypeScript definitions, and test coverage to avoid breaking consuming applications. ref as a Prop: Migrating Away From forwardRef Across a Large Component Library This article was written with the assistance of AI, under human supervision and review. Most React component library maintenance debt stems from a single historical artifact: forwardRef . The pattern emerged because refs were special-cased in React's original architecture—passing them required wrapping every component that needed to expose a DOM handle. Component library teams spent years adding forwardRef wrappers to hundreds of components, maintaining parallel prop interfaces, and explaining to developers why some components accepted refs while others did not. React 20 eliminates this complexity by treating ref as a standard prop. The wrapper disappears. The special case vanishes. Teams maintaining component libraries face a straightforward migration path, but the execution requires deliberate planning across versioning, TypeScript definitions, and test coverage. React 20's approach removes the wrapper entirely. The ref prop flows through component props like className or onClick . TypeScript inference improves because the prop interface becomes a single object instead of a split between props and ref parameters. This distinction is critical. Component libraries shipping to thousands of projects must execute this migration without breaking consuming applications. The path forward balances backward compatibility, versioning hygiene, and TypeScript correctness. ref as a standard prop, eliminating the need for forwardRef wrappers in all component definitions. ref as a prop field and removing forwardRef function wrappers from component exports.React's original architecture treated refs as a special case because the reconciler needed direct control over DOM element references during commit phases. The forwardRef API emerged as a workaround—a way to thread refs through component boundaries when the props object deliberately excluded them. This created a bifurcation in how developers thought about component APIs: regular props went through the props object, but refs required a separate code path. The consequence was immediate and pervasive. Every component library that exposed DOM elements to consumers needed forwardRef wrappers. A simple button component became a higher-order function. TypeScript definitions split into two parts: the props interface and the ref type parameter. Documentation had to explain why some components accepted refs while others did not, even when both rendered DOM elements. React 20 resolves this by integrating ref handling directly into the reconciler's props diffing algorithm. When the reconciler processes a component's props, it now handles ref assignments the same way it handles event handlers or style objects. The special case disappears from the API surface. The implication here is that component library authors no longer maintain two parallel APIs for the same component. A button that accepts onClick can accept ref through the same props object. TypeScript inference works uniformly across all props. The cognitive overhead of explaining ref forwarding to new team members vanishes. This matters because component libraries often contain hundreds of components. Each forwardRef wrapper represents a maintenance point—a place where TypeScript generics might drift, where documentation must stay synchronized, where automated refactoring tools struggle. Eliminating these wrappers reduces the surface area for bugs and simplifies onboarding for contributors. The first step in any large-scale migration is establishing which components require changes. Not every component in a library uses forwardRef , and not every component that renders a DOM element needs to expose a ref. The migration targets components where external consumers expect to attach refs—typically leaf components that wrap native HTML elements or third-party DOM-producing libraries. Start by scanning the codebase for forwardRef imports. A simple grep or AST-based search identifies these components immediately. Cross-reference this list against the library's public API documentation. Any component documented as "ref-capable" must be updated, even if the current implementation does not use forwardRef . The second filter is usage data. If the library has telemetry or download statistics, prioritize components that appear in the most consuming projects. A button component with 50,000 weekly downloads demands migration before an obscure utility component with 200. This prioritization lets teams ship incremental releases, spreading the migration risk across multiple versions. Components that render other components from the same library typically do not need changes. If a Card component renders a Button , and both are in the same library, the Card does not need to forward refs—the consuming application attaches refs directly to the Button . This reduces the migration scope significantly in libraries with deep component hierarchies. The edge cases appear in higher-order components and render prop patterns. A HOC that wraps an arbitrary component must decide whether to expose the wrapped component's ref. In React 19, this required forwardRef at the HOC level. In React 20, the HOC accepts ref as a prop and passes it through manually. The pattern changes, but the core logic remains. The mechanical transformation from forwardRef to a standard prop follows a consistent pattern. Here is a typical button component in React 19: js import { forwardRef, ButtonHTMLAttributes } from 'react'; interface ButtonProps extends ButtonHTMLAttributes