Last updated: Apr 7, 2024
Reading time·4 min

The React warning "Function components cannot be given refs. Attempts to
access this ref will fail. Did you mean to use React.forwardRef()?" occurs when
you pass the ref prop to a function component.
To resolve the issue, pass a prop of a different name to the component, e.g.
inputRef or use React.forwardRef().

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Here is an example of how the warning occurs.
import React, {useRef} from 'react'; export default function App() { const inputRef = useRef(null); return ( <div> <h2>bobbyhadz.com</h2> <Input ref={inputRef} /> </div> ); } // ⛔️ Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()? const Input = ({ref}) => { return ( <div> <input id="message" name="message" ref={ref} /> </div> ); };
We can't set the ref prop on function components, such as Input.
However, we could rename the ref prop to something else, e.g. innerRef.
Here is the updated code that resolves the issue.
import React, {useRef} from 'react'; export default function App() { const inputRef = useRef(null); return ( <div> <h2>bobbyhadz.com</h2> <Input innerRef={inputRef} /> </div> ); } const Input = ({innerRef}) => { const logInputValue = () => { console.log(innerRef.current.value); }; return ( <div> <input id="message" name="message" ref={innerRef} /> <button onClick={logInputValue}>Log value</button> </div> ); };

We are no longer passing a ref prop to the Input component.
Instead, we passed an innerRef prop to the component and set the ref prop
on the input element.
The ref prop can only be set on JSX elements, such as input, textarea,
etc.
The prop cannot be set on function components, such as Input (capital I).
The easiest way to get around this is to simply pass a prop of a different name as shown in the code sample.
Note that the name of the prop doesn't have to be innerRef, you could use any
other value as long as you don't use the ref prop name.
React.forwardRef() method to resolve the issueYou can also use the React.forwardRef() method to resolve the issue.
import React, {useRef, forwardRef} from 'react'; export default function App() { const inputRef = useRef(null); return ( <div> <h2>bobbyhadz.com</h2> <Input ref={inputRef} /> </div> ); } const Input = forwardRef((props, ref) => { const logInputValue = () => { console.log(ref.current.value); }; return ( <div> <input id="message" name="message" ref={ref} /> <button onClick={logInputValue}>Log value</button> </div> ); });

Ref forwarding enables components to take a ref and pass it further down (forward it) to a child.
Notice that we passed the ref prop to the Input component (and not
innerRef).
The Input component uses the forwardRef method to get the ref that was
passed to it and sets the ref prop on an input element.
React automatically passes the ref to the (props, ref) => {} function
inside forwardRef as the second argument.
When the ref prop is set on the input element, the ref.current property
refers to the input element.
Note that the second ref argument is only passed when you define a component
with React.forwardRef.
Regular React function components only get passed a props object argument.
You might also get the error when using custom components from third-party libraries.
If you got the error when using the Link component in Next.js with another
custom component, try to wrap the custom component in an <a> tag.
Before:
<Link href="/login"> <NavLink style={{ cursor: "pointer" }}>Login</NavLink> </Link>
After:
<Link href="/login" passHref> <a> <NavLink style={{ cursor: "pointer" }}>Login</NavLink> </a> </Link>
I simply wrapped the NavLink with an a element and set the passHref prop.
This way, the ref will get passed to the <a> HTML element and not the
NavLink function component.
This works in a similar way when using other custom components - wrap the
component that causes the issue with a div tag.
Before:
<Link href='/'> <CustomImage /> </Link>
After:
<Link href='/'> <div> <CustomImage /> </div> </Link>
I simply wrapped the CustomImage component with a div tag so the ref prop
gets passed to the div and not to the function component.
ref prop on a wrapper div elementAn alternative solution that might or might not work depending on your use case
is to wrap the function component with a div and set the ref prop on the
wrapper div element.
import React, {useRef} from 'react'; export default function App() { const inputRef = useRef(null); return ( <div> <h2>bobbyhadz.com</h2> <div ref={inputRef}> <Button>Click</Button> </div> </div> ); } function Button({children}) { return <button>{children}</button>; }
TextField components from material UIIf you use the material UI library, note
that you have to set the inputRef prop on TextField elements instead of
ref.
import React, {useRef} from 'react'; import TextField from '@mui/material/TextField'; export default function App() { const inputRef = useRef(null); const logInputValue = () => { console.log(inputRef.current); console.dir(inputRef.current.value); }; return ( <div> <h2>bobbyhadz.com</h2> <TextField inputRef={inputRef} id="outlined-basic" label="Outlined" variant="outlined" defaultValue="" /> <button onClick={logInputValue}>Click</button> </div> ); }

Notice that we set the inputRef prop on the TextField component and not the
ref prop.
This is the case because the TextField component contains many nested DOM
elements and setting the ref prop on the outermost element is not what we
need.