React 19-compatible forwardRef utility for Bento
npm install @bento/forwardThe @bento/forward package provides the withForwardRef utility for React 19-compatible ref forwarding. It automatically detects whether your component needs forwardRef wrapping and applies it only when necessary.
``shell`
npm install --save @bento/forward
The withForwardRef utility wraps functional components with forwardRef in React 18 when they might accept a ref parameter.
Wrapping occurs when Component.length !== 1:
- length === 0 - Rest parameters: function Component(...args) - Wrappedlength === 2
- - Explicit ref: function Component(props, ref) - Wrappedlength === 1
- - Props only: function Component(props) - Not wrapped
React 19: No wrapping needed - refs are passed as props natively.
| Component Pattern | React 18 | React 19 |
|------------------|----------|----------|
| function Component(props, ref) | Wrapped | Unchanged |function Component(...args)
| | Wrapped | Unchanged |function Component(props)
| | Unchanged | Unchanged |React.forwardRef(Component)
| | Unchanged | Unchanged |
Component with 2 parameters will be automatically wrapped in React 18:
`tsx
import { withForwardRef } from '@bento/forward';
/ v8 ignore next /
import React from 'react';
interface BasicExampleProps {
children?: React.ReactNode;
className?: string;
}
/**
* Basic example showing withForwardRef with a component that has 2 parameters.
* In React 18, this will be automatically wrapped with forwardRef.
* In React 19, it returns the component unchanged (refs are passed as props).
*
* @public
*/
export const BasicExample = withForwardRef
props,
ref: React.ForwardedRef
) {
return (
{props.children}
);
});
`
Component using rest parameters for the future useProps(...args) API:
`tsx
import { withForwardRef } from '@bento/forward';
/ v8 ignore next /
import React from 'react';
interface RestParamsProps {
children?: React.ReactNode;
className?: string;
}
/**
* Example showing withForwardRef with rest parameters (...args).
* This pattern is useful for the future useProps(...args) API.
* In React 18, this will be automatically wrapped with forwardRef.
*
* @public
*/
export const RestParams = withForwardRef
// Future API pattern: const { props, ref } = useProps(args, state);
// For now, just demonstrate the pattern
const [props, ref] = args;
return (
$3
Components already wrapped with
forwardRef are returned unchanged:`tsx
import { withForwardRef } from '@bento/forward';
/ v8 ignore next /
import React from 'react';interface AlreadyWrappedProps {
children?: React.ReactNode;
}
/**
* Example showing withForwardRef with a component already using React.forwardRef.
* The component is returned unchanged since it's already wrapped.
*
* @public
*/
export const AlreadyWrapped = withForwardRef(
React.forwardRef(function AlreadyWrapped(props, ref) {
return {props.children};
})
);
`$3
Components that don't accept a ref parameter are returned unchanged:
`tsx
import { withForwardRef } from '@bento/forward';
/ v8 ignore next /
import React from 'react';interface NoRefProps {
children?: React.ReactNode;
}
/**
* Example showing withForwardRef with a component that doesn't accept a ref.
* The component is returned unchanged since it doesn't need ref forwarding.
*
* @public
*/
export const NoRef = withForwardRef(function NoRef(props) {
return {props.children};
});
`Migration from React 18 to React 19
Components using
withForwardRef will work seamlessly when upgrading from React 18 to React 19 with no code changes required. The utility handles the difference automatically.API
$3
Wraps a component with
forwardRef if needed for React 18 compatibility.Parameters:
-
Component: React.ComponentType - The component to wrapReturns:
-
React.ComponentType - The component, optionally wrapped with forwardRef`