javascriptreactjsreact-forwardref

React forwardRef - access ref within component, and in parent


I need to access the ref to a textarea inside a component. Within the component, its easy enough:

const MyComponent = () => {
  const inputRef = useRef();

  return <textarea ref={inputRef} />
}

Now the ref is available within MyComponent and I can use it for some internal logic.

There are cases where I need to access the ref from the parent component as well. In that case, I can use forwardRef:

const MyComponent = React.forwardRef((props, ref) => {
  return <textarea ref={ref} />
})

// In some parent
const MyParent = () => {
  const inputRefFromParent = useRef();
  return <MyComponent ref={inputRefFromParent} />
}

Now I can access to ref of the textarea from the parent component, and use it for logic within the parent component.

I find myself in a situation where I need to do some internal logic with the ref within MyComponent, but I may also need to get that ref from MyParent. How can I do this?


Solution

  • You can keep a ref in the MyComponent and expose what you would need in the parent component using useImperativeHandle hook using the ref passed from the MyParent.

    Try like below. It exposes the focus method in the textarea to parent. And you can do any other internal things with the access to textAreaRef.

    import { useRef, forwardRef, useImperativeHandle } from "react";
    
    const MyComponent = forwardRef((props, ref) => {
      const textAreaRef = useRef();
    
      // all the functions or values you can expose here
      useImperativeHandle(ref, () => ({
        focus: () => {
          textAreaRef.current.focus();
        }
      }));
    
      const internalFunction = () => {
        // access textAreaRef
      };
    
      return <textarea ref={textAreaRef} />;
    });
    
    // In some parent
    const MyParent = () => {
      const inputRefFromParent = useRef();
    
      // you can call inputRefFromParent.current.focus(); in this compoenent
      return <MyComponent ref={inputRefFromParent} />;
    };