Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use React.forwardRef() with own ref in the component?

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}/>
})

Thanks a lot for your answers.
like image 630
xNevrroXx Avatar asked Nov 27 '25 06:11

xNevrroXx


2 Answers

To access a ref while also forwarding it, it is simpler to do the following:

  • Attach a ref created inside the component to the element.
  • Call the 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} />;
});
like image 123
Unmitigated Avatar answered Nov 29 '25 00:11

Unmitigated


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.

like image 36
Alexandre Oliveira Avatar answered Nov 29 '25 01:11

Alexandre Oliveira



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!