This React warning appears when your forwardRef callback function does not accept exactly two parameters: props and ref. React enforces this signature to ensure refs are properly forwarded to child components.
This warning is triggered by React's validation system when you use React.forwardRef with a render function that doesn't match the expected signature. React.forwardRef is designed to forward refs from parent components to child components, particularly useful for custom components that need to expose their underlying DOM nodes or instances. The forwardRef API expects a render function that receives exactly two parameters: props (the component's properties) and ref (the forwarded reference). React enforces this constraint because the ref forwarding mechanism relies on this specific function signature. When React calls your render function, it passes the props as the first argument and the forwarded ref as the second argument. This validation helps catch common mistakes such as forgetting to include the ref parameter, adding extra parameters beyond props and ref, or using destructuring syntax that doesn't properly capture both parameters. The warning serves as a reminder that if you're using forwardRef, you must handle both the props and ref parameters appropriately, even if you don't actively use the ref in your component logic.
Locate the component using forwardRef and verify its function signature. The callback must accept exactly two parameters:
// ❌ Wrong - only one parameter
const MyComponent = forwardRef((props) => {
return <input {...props} />;
});
// ❌ Wrong - three or more parameters
const MyComponent = forwardRef((props, ref, extra) => {
return <input {...props} ref={ref} />;
});
// ✅ Correct - exactly two parameters
const MyComponent = forwardRef((props, ref) => {
return <input {...props} ref={ref} />;
});Even if you don't plan to use the ref, you must declare it as the second parameter.
If you're using object destructuring for props, ensure you still declare the ref as a separate parameter:
// ❌ Wrong - ref is missing
const Input = forwardRef(({ value, onChange }) => {
return <input value={value} onChange={onChange} />;
});
// ✅ Correct - props destructured, ref declared separately
const Input = forwardRef(({ value, onChange }, ref) => {
return <input value={value} onChange={onChange} ref={ref} />;
});The ref must always be the second parameter, separate from props destructuring.
Once you have both parameters declared, attach the ref to the appropriate element in your JSX:
const TextInput = forwardRef((props, ref) => {
return (
<div className="input-wrapper">
<input ref={ref} {...props} />
</div>
);
});
// Usage in parent component
function ParentComponent() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current?.focus(); // Now works correctly
}, []);
return <TextInput ref={inputRef} placeholder="Type here" />;
}The ref should be passed to the underlying DOM element or component that you want to expose to the parent.
When using TypeScript, ensure your types match the forwardRef signature:
import { forwardRef, InputHTMLAttributes } from 'react';
// Define props type
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
label?: string;
}
// ✅ Correct TypeScript usage
const Input = forwardRef<HTMLInputElement, InputProps>(
({ label, ...props }, ref) => {
return (
<div>
{label && <label>{label}</label>}
<input ref={ref} {...props} />
</div>
);
}
);
Input.displayName = 'Input';Note that the generic order is <RefType, PropsType>, which is opposite to the parameter order (props, ref).
If you're not actually using the ref parameter in your component, evaluate whether you need forwardRef at all:
// If you added forwardRef but don't use the ref...
const Button = forwardRef((props, ref) => {
// ref is never used here
return <button {...props}>{props.children}</button>;
});
// Consider just using a regular component instead
const Button = (props) => {
return <button {...props}>{props.children}</button>;
};Only use forwardRef when you specifically need to expose a ref to parent components. Regular function components are simpler and don't require the two-parameter signature.
If you need to customize what the ref exposes, combine forwardRef with useImperativeHandle:
import { forwardRef, useImperativeHandle, useRef } from 'react';
const CustomInput = forwardRef((props, ref) => {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current?.focus();
},
clear: () => {
if (inputRef.current) {
inputRef.current.value = '';
}
}
}));
return <input ref={inputRef} {...props} />;
});
CustomInput.displayName = 'CustomInput';This pattern still requires the correct two-parameter signature for forwardRef.
Add a displayName to your forwarded component for clearer React DevTools output:
const MyComponent = forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
// This helps identify the component in DevTools
MyComponent.displayName = 'MyComponent';
// Without displayName, DevTools shows "ForwardRef(Anonymous)"
// With displayName, DevTools shows "ForwardRef(MyComponent)"While this doesn't fix the warning, it makes debugging easier once your component is properly configured.
TypeScript Generic Components: When creating generic components with forwardRef, you may need to use declaration merging or type casting. The standard forwardRef type doesn't support generics out of the box. See the TypeScript React Cheatsheet for patterns to handle this.
React DevTools: ForwardRef components appear as "ForwardRef(ComponentName)" in React DevTools. Setting the displayName property helps identify them more easily during debugging.
Performance Considerations: forwardRef itself has minimal performance impact, but unnecessary ref forwarding can complicate your component tree. Only use it when parent components actually need access to the underlying DOM node or component instance.
Class Components: You don't need forwardRef for class components—they automatically support refs via the ref attribute. forwardRef is specifically for function components that need to expose refs.
Multiple Refs: If you need to forward a ref while also using it internally, combine useRef with useImperativeHandle, or use a callback ref to handle both the internal and forwarded ref.
Linting Rules: ESLint with the react-hooks plugin includes rules that can detect useless forwardRef usage (when the ref parameter is declared but never used). Consider enabling these rules to catch unnecessary complexity.
React 19 Changes: Be aware that future React versions may change how refs are handled. The current forwardRef pattern is stable in React 16.3+, but stay updated with React's official documentation for any API changes.
React.FC expects children prop to be defined
React.FC no longer includes implicit children prop
Warning: You provided a `selected` prop to a form field without an `onChange` handler
You provided a 'selected' prop without an onChange handler
Failed to load source map from suspense chunk
How to fix "Failed to load source map from suspense chunk" in React
Prop spreading could cause security issues
Prop spreading could cause security issues
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency