refをフォワーディングして子コンポーネントのDOM操作を行おう

Posted: 2020/9/13
React/
Ref

この記事を読む前に、Ref についての記事 を読むことをお勧めします!

ref のフォワーディングとは、親コンポーネントから子コンポーネントに ref を渡すテクニックで、これにより子コンポーネントの DOM 操作などを行うことができます。

それでは、具体的な方法を見ていきましょう!

ref フォワーディング

順を追って ref フォワーディングの実装順について説明します。

  • まず、React.createRefで Ref オブジェクトを作り、それを子コンポーネントに<Button ref={ref}> のように ref 属性に指定します。
  • 子コンポーネントでReact.forwardRef() を用いて受け取ります。forwardRef は引数にpropsrefの順で受け取ります。
  • 受け取った ref を操作したい DOM ノードの ref 属性に指定します。

この手順を通すと、ref.current は操作したい子コンポーネントの DOM ノードを指すようになります。

例を以下に示します。

// forwardRefでrefを受け取り、操作したいDOMノードのref属性に指定する
const ForwardingButton = React.forwardRef((props, ref) => (
  <button ref={ref}>{props.children}</button>
));

// Refオブジェクトを作り、子コンポーネントのref属性に指定
const ref = React.createRef();
<ForwardingButton ref={ref}>Click me!</ForwardingButton>;

補足

ref フォワーディングを使わずに、つまりReact.forwardRef を用いない方法で親から子のコンポーネントに ref を渡そうとするとエラーが出ます!

基本的に子コンポーネントの DOM 操作などを行いたい場合は ref フォワーディングを使いましょう。

また、ref のフォワーディング先は DOM ノードだけではなく、クラスコンポーネントのインスタンスに対してもフォワーディングすることができます。

高階コンポーネントでの ref フォワーディング

HOC で forwardRef を使う例を以下に示します。

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;

      // forwardedRefという名のpropsをrefとして受け取り、コンポーネントに紐づける
      return <Component ref={forwardedRef} {...rest} />;
    }
  }
  // forwardRefの第二引数でrefを受け取り、コンポーネントに紐づけている
  return React.forwardRef((props, ref) => {
    return <LogProps {...props} forwardedRef={ref} />;
  });
}