【React】自作コンポーネントに ref 属性を渡す方法

  • React

普通に ref を渡してみるとエラーになる

下記のようなオリジナル Hoge コンポーネントがあるとしましょう。input が div で囲まれるだけの味気ないコンポーネントです。

export const Hoge = (props) => {
  const { ...restProps } = props;
  return ( 
    <div>
      <input {...restProps} />
    </div>
  );
}

他のコンポーネントからこの Hoge コンポーネントを呼び出して、ref を渡してみると…

import Hoge from 'Hoge.tsx';

const ref = React.useRef();
return (
  <Hoge ref={ref} /> // ref をどうぞ〜
);

エラーが出て怒られます。

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

どうやら、Function Components は ref を受け取れないようです。代わりに、「React.forwardRef()を使いたかったんだろ?」と言われます。

ref を渡せるようにする

React.forwardRef()を使って、Input コンポーネントで ref を受け取れるようにします。

Input コンポーネント

React.forwardRef()でラップするだけです。このコールバック関数では props, ref の2つを受け取ります。

export const Hoge = React.forwardRef((props, ref) => {
  const { ...restProps } = props;
  return ( 
    <div>
      <input {...restProps} ref={ref} />
    </div>
  );
})

ref を渡す

const ref = React.useRef();
console.log(ref.current);

return <Hoge ref={ref} />

Input コンポーネントに ref を渡して、ref.currentの中身を確認してみると、オリジナル Hoge コンポーネントの中の input 要素が取得できます。

Component definition is missing display name と言われる

ちゃんと調べてませんが、React.forwardRef()でラップした時に eslint の設定か何かで怒られることがあります。

Component definition is missing display nameeslintreact/display-name

コンポーネントの名前がないとだめ?と言われるっぽいので、アロー関数をやめて function で名前付き関数を定義すると解消されます。

export const Hoge = React.forwardRef((props, ref) => { ... });
↓
export const Hoge = React.forwardRef(function Hoge(props, ref) = { ... });

参考

https://ja.reactjs.org/docs/forwarding-refs.html