Task
I'm trying to use React.forwardRef() and in the same time use React.useRef() in a component.
Problem
I can use either only myOwnRef or ref from forwardRef prop. So, I have no idea how to use them together.
Example code:
interface IExampleInputProps {
value: string,
onChange: (event: ChangeEvent<HTMLInputElement>) => void
}
const ExampleInput = forwardRef<HTMLInputElement | null, IExampleInputProps>(({value, onChange}, ref) => { // can't to use "ref" parameter
const myOwnRef = React.useRef<HTMLInputElement | null>(null);
return <input ref={el => {
myOwnRef.current = el; // => OK
if (ref) { // trying to use the ref passed from the forwardRef function
ref.current = el; // => ERROR
}
}} value={value} onChange={onChange}/>
})
To access a ref while also forwarding it, it is simpler to do the following:
useImperativeHandle hook on the outer ref (which is being forwarded to) and pass a function that returns the current property of the inner ref, which is the value that will be set to the current property of the outer ref.import { forwardRef, useImperativeHandle, useRef } from 'react';
const MyComponent = forwardRef<HTMLInputElement, IExampleInputProps>(({value, onChange}, outerRef) => {
const innerRef = useRef<HTMLInputElement>(null);
useImperativeHandle(outerRef, () => innerRef.current!, []);
// remember to list any dependencies of the function that returns the ref value, similar to useEffect
return <input ref={innerRef} value={value} onChange={onChange} />;
});
The suggestion of useImperativeHandle hasn't worked on my use case.
So, I made like this:
import { forwardRef, useRef } from 'react';
const MyComponent = forwardRef<HTMLInputElement, IExampleInputProps>(({value, onChange}, outerRef) => {
const innerRef = useRef<HTMLInputElement>(null);
const refToUse = !outerRef || typeof outerRef === 'function' ? innerRef : outerRef;
useEffect(() => {
// Example
refToUse.current.focus();
})
return <input ref={refToUse } value={value} onChange={onChange} />;
});
Although, I haven't liked this solution I made, it has worked on my use case.
Important to note that if you pass a function to the outerRef won't work as expected.
On my project I only pass MutableRefObject to it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With