Пересылка Refs - это метод передачи ref через компонент одному из его потомков. Этот метод может быть особенно полезен для компонентов более высокого порядка (также известных как HOC).

Начнем с примера HOC, который регистрирует реквизиты компонента на консоли:

function logProps(WrappedComponent) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }

    render() {
      return <WrappedComponent {...this.props} />;
    }
  }

  return LogProps;
}

«LOGProps» HOC проходит propsчерез весь компонент, который он обертывает, поэтому визуализированный вывод будет таким же. Например, мы можем использовать этот HOC для регистрации всех реквизитов, которые передаются нашему компоненту «причудливой кнопки»:

class FancyButton extends React.Component {
  focus() {
    // ...
  }

  // ...
}

// Rather than exporting FancyButton, we export LogProps.
// It will render a FancyButton though.
export default logProps(FancyButton);

В приведенном выше примере есть одно предостережение: refs не пройдет. Это потому, что ref это не опора. Как key, Реакт по-разному обрабатывается по-разному. Если вы добавите ref в HOC, ref будет ссылаться на внешний контейнерный компонент, а не на завернутый компонент.

Это означает, что ссылки, предназначенные для нашего FancyButton компонента, будут фактически привязаны к LogProps компоненту:

import FancyButton from './FancyButton';

const ref = React.createRef();

// The FancyButton component we imported is the LogProps HOC.
// Even though the rendered output will be the same,
// Our ref will point to LogProps instead of the inner FancyButton component!
// This means we can't call e.g. ref.current.focus()
<FancyButton
  label="Click Me"
  handleClick={handleClick}
  ref={ref}
/>;

К счастью, мы можем явно перенаправить ссылки на внутренний FancyButton компонент с помощью React.forwardRefAPI. React.forwardRef принимает функцию рендеринга, которая получает props и ref параметры, и возвращает узел React. Например:

function logProps(Component) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }

    render() {
      const {forwardedRef, ...rest} = this.props;

      // Assign the custom prop "forwardedRef" as a ref
      return <Component ref={forwardedRef} {...rest} />;
    }
  }

  // Note the second param "ref" provided by React.forwardRef.
  // We can pass it along to LogProps as a regular prop, e.g. "forwardedRef"
  // And it can then be attached to the Component.
  function forwardRef(props, ref) {
    return <LogProps {...props} forwardedRef={ref} />;
  }

  // These next lines are not necessary,
  // But they do give the component a better display name in DevTools,
  // e.g. "ForwardRef(logProps(MyComponent))"
  const name = Component.displayName || Component.name;
  forwardRef.displayName = `logProps(${name})`;

  return React.forwardRef(forwardRef);
}