リファレンス

forwardRef(render)

forwardRef() を呼び出すことで、コンポーネントが ref を受け取ってそれを子コンポーネントに転送 (forward) できるようになります。

引数

  • render: コンポーネントのレンダー関数です。React はこの関数を親から受け取った props および ref とともに呼び出します。返す JSX がコンポーネントの出力となります。

返り値

forwardRef は JSX でレンダーできる React コンポーネントを返します。プレーンな関数として定義された React コンポーネントとは異なり、forwardRef によって返されるコンポーネントは ref 属性を受け取ることもできます。

注意点

  • Strict Mode では、React はため、レンダー関数を 2 回呼び出します。これは開発環境専用の挙動であり、本番環境には影響しません。レンダー関数が純粋である場合(そうであるべきです)、これはコンポーネントのロジックに影響を与えません。呼び出しのうちの一方からの結果は無視されます。

render 関数

forwardRef は引数としてレンダー関数を受け取ります。React はこの関数を props および ref とともに呼び出します。

引数

  • props: 親コンポーネントから渡された props です。

  • ref: 親コンポーネントから渡された ref 属性です。ref はオブジェクトの場合と関数の場合があります。親コンポーネントが ref を渡していない場合は null になります。受け取った ref は、別のコンポーネントに渡すか、 に渡します。

返り値

forwardRef は JSX でレンダーできる React コンポーネントを返します。プレーンな関数として定義された React コンポーネントとは異なり、forwardRef によって返されるコンポーネントは ref 属性を受け取ることができます。


使用法

親コンポーネントに DOM ノードを公開する

デフォルトでは、各コンポーネント内の DOM ノードはプライベートです。しかし、時には親に DOM ノードを公開することが有用な場合があります。例えば、ノードにフォーカスを当てることを許可したい場合です。これを明示的に許可するために、コンポーネント定義を forwardRef() でラップします。

props の後の第 2 引数として ref が渡されます。公開したい DOM ノードにそれを渡してください。

これで、親の Form コンポーネントが、MyInput によって公開された <input> DOM ノードにアクセスできるようになります。

この Form コンポーネントは MyInput に 。MyInput コンポーネントはその ref をブラウザの <input> タグに転送しています。その結果、Form コンポーネントはこの <input> DOM ノードにアクセスし、 を呼び出すことができるようになります。

コンポーネント内の DOM ノードへの ref を公開することで、後でコンポーネントの内部を変更するのが難しくなることに注意してください。通常は、ボタンやテキスト入力フィールドなどの再利用可能な低レベルコンポーネントからは DOM ノードの公開を行いますが、アバターやコメントのようなアプリケーションレベルのコンポーネントでは行いません。


複数コンポーネントを経由した ref の転送

ref を DOM ノードに転送する代わりに、独自コンポーネントである MyInput に転送することもできます。

さらにその MyInput コンポーネントが自身の <input> に ref を転送すれば、FormField への ref はその <input> への参照を受け取ることになります。

Form コンポーネントは ref を定義し、それを FormField に渡しています。FormField コンポーネントはその ref を MyInput に転送し、MyInput はそれをブラウザの <input> DOM ノードに転送しています。これで Form が DOM ノードにアクセスできるようになります。


DOM ノードの代わりに命令型ハンドルを公開する

DOM ノードをまるごと公開する代わりに、使用できるメソッドを制限したカスタムオブジェクトである、命令型ハンドル (imperative handle) を公開することができます。これを行うには、DOM ノードを保持するための別の ref を定義します。

そして受け取った ref を に渡し、ref で公開したい値を指定します。

何らかのコンポーネントが MyInput への ref を取得すると、DOM ノードの代わりにあなたが書いた { focus, scrollIntoView } というオブジェクトを受け取ります。これにより、DOM ノードについて公開する情報を最小限に制限することができます。


トラブルシューティング

コンポーネントを forwardRef でラップしているのに、ref が常に null になる

これは通常、受け取った ref を実際に使用するのを忘れていることを意味します。

例えば、このコンポーネントは ref を全く使用していません:

修正するにはこの ref を、DOM ノードか、ref を受け入れることができる別のコンポーネントに渡します。

一部のロジックが条件付きである場合にも、MyInput への refnull になることがあります。

showInputfalse の場合、ref はどのノードにも転送されないため、MyInput への ref は空のままになります。特に、以下の例のように条件が別のコンポーネント、例えば Panel の中に隠されている場合、これを見落としがちです。