React throws this warning when you attach a ref object or callback to a function component because the component does not expose an instance for React to assign the ref. The runtime is protecting you from leaking a DOM node reference into a place that cannot safely receive it.
React only assigns non-string refs (object refs or callbacks) to DOM elements and class components because they expose an instance for the ref to point at. Function components do not have instances, so when a parent tries to set a ref on one of them, React warns instead of failing silently. The proper fix is to either move the ref down to the DOM node rendered by the function component or wrap the component with `React.forwardRef` so it can explicitly hand the ref to a DOM node or an imperative handle. If you still need to expose some imperative API, use `forwardRef` together with `useImperativeHandle` so you control exactly what the parent sees. Avoid relying on string refs because they are legacy and were never supported on function components in the first place.
If the child function component simply renders a DOM element, move the ref to that element and expose any public APIs through props instead. Example:
function TextInput(props: {}) {
const inputRef = useRef<HTMLInputElement>(null);
useImperativeHandle(props.forwardedRef, () => ({
focus: () => inputRef.current?.focus(),
}));
return <input ref={inputRef} />;
}
const ForwardedTextInput = forwardRef((props, ref) => (
<TextInput {...props} forwardedRef={ref} />
));This keeps the actual DOM reference inside the component while still letting the parent interact with the exposed methods.
React cannot make refs point at function components unless you opt into forwarding. Wrap the component declaration with forwardRef and pass the ref down to a DOM node or into useImperativeHandle:
const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => (
<button ref={ref} {...props} />
));Now parents can safely attach refs to <Button /> without hitting the warning.
Not every function component automatically accepts refs. Inspect the documentation or source code of libraries (e.g., React Router, Radix UI, etc.) to see if they expose a forwardRef API or supply a helper prop such as componentRef.
If the component cannot forward refs, wrap it with another forwardRef container that renders a DOM node you control and forwards the ref there.
String refs are legacy and have never worked on function components. Stick with const ref = useRef<T>(), createRef(), or callback refs and keep them attached to DOM nodes. When you need to forward them through multiple layers, explicitly forward the ref at each layer.
String refs are legacy, difficult to type, and slated for removal (see React docs). Always pass objects or callbacks to ref, and keep forwardRef/ useImperativeHandle handy when you need to expose imperative handles from function components.
Function components cannot receive string refs because React never created an instance for them. Even when you bind callbacks, React still needs to resolve the ref to an actual DOM node or class instance, so you still must forward it explicitly.
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
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite