React – Forwarding multiple refs

I know there is an already accepted answer, and while I find @nicholas-haley’s solution acceptable.
I think a better way to go about it would be to use the built-in useImperativeHandle hook.

IMPORTANT: The React Hooks Api is available as of

  • react@16.8.0 and later
  • react-native@0.59.0 and later

The React hooks API Docs state:

useImperativeHandle customizes the instance value that is exposed to parent components when using ref. As always, imperative code using refs should be avoided in most cases. useImperativeHandle should be used with `forwardRef

This note is followed by the following example:

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);

Thus, in my opinion, a much cleaner solution would be to delegate the needed refs through the useImperativeHandle hook.

This way there is no need for a special ref syntax, and the component can simply return a specific type of a FatherRef; Example:

// LabelInput.js
function LabelInput(props, ref) {
    const labelRef = useRef();
    const inputRef = useRef();

    useImperativeHandle(ref, () => ({
      focus: () => {
       inputRef.current.focus();
      },
      get input() {
          return inputRef.current;
      },
      get label() {
          return labelRef.current;
      },
      // ... whatever else one may need
    }));
    return (
      <div>
        <label ref={labelRef} ... />
        <input ref={inputRef} ... />;
      </div>
    )
}
LabelInput = forwardRef(LabelInput);

function MyScreen() {
   const labelInputRef = useRef();

   const onClick = useCallback(
    () => {
//       labelInputRef.current.focus(); // works
//       labelInputRef.current.input.focus(); // works
// ... etc
    },
    []
   );

   return (
     ...
      <LabelInput ref={labelInputRef} ... />
     ....
   )
}

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)