@bento/forward
v0.1.0
Published
React 19-compatible forwardRef utility for Bento
Readme
Forward
The @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.
Installation
npm install --save @bento/forwardHow It Works
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 |
Examples
Basic Usage
Component with 2 parameters will be automatically wrapped in React 18:
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<BasicExampleProps>(function BasicExample(
props,
ref: React.ForwardedRef<HTMLDivElement>
) {
return (
<div ref={ref} className={props.className}>
{props.children}
</div>
);
});Rest Parameters (Spread)
Component using rest parameters for the future useProps(...args) API:
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<RestParamsProps>(function RestParams(...args: any[]) {
// Future API pattern: const { props, ref } = useProps(args, state);
// For now, just demonstrate the pattern
const [props, ref] = args;
return (
<div ref={ref} className={props?.className}>
{props?.children}
</div>
);
});Already Using forwardRef
Components already wrapped with forwardRef are returned unchanged:
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<HTMLDivElement, AlreadyWrappedProps>(function AlreadyWrapped(props, ref) {
return <div ref={ref}>{props.children}</div>;
})
);Component Without Ref
Components that don't accept a ref parameter are returned unchanged:
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<NoRefProps>(function NoRef(props) {
return <div>{props.children}</div>;
});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
withForwardRef<Props>(Component)
Wraps a component with forwardRef if needed for React 18 compatibility.
Parameters:
Component: React.ComponentType<Props>- The component to wrap
Returns:
React.ComponentType<Props>- The component, optionally wrapped withforwardRef
