forwardRef
リファレンス
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
への ref
が null
になることがあります。
showInput
が false
の場合、ref はどのノードにも転送されないため、MyInput
への ref は空のままになります。特に、以下の例のように条件が別のコンポーネント、例えば Panel
の中に隠されている場合、これを見落としがちです。