役割
- reactの要素(子要素)にアクセスする方法の一つ。
- 一般的には、親から子にpropsを渡して子をレンダリングするが、その方法以外で子にアクセスする。親から子を命令型のコードを使って操作する。
いつ使うのか
- フォーカス、テキストの選択、メディアの再生の管理
- アニメーション発火
- サードパーティのDOMライブラリとの統合
Refの使い方
- 特定の操作で反応させたいDOMにアクセスするために使う。
関数コンポーネントにはrefを渡すことができない。
- なぜ?
- 関数コンポーネントはインスタンスを持たないobjectのため。
- Refは通常、コンポーネントの構築時にインスタンスプロパティに割り当てられる
どうすれば子をrefで操れるの?
- インスタンスを持たない関数コンポーネントに対してRefを使いたい場合、
forwardRef
を利用する or クラスコンポーネントに書き換える。
*公式引用
- React 16.3 以降を使用している場合[ref のフォワーディング](https://ja.reactjs.org/docs/forwarding-refs.html) を使用するのがよい
- Ref のフォワーディングを使うと、コンポーネントは任意の子コンポーネントの ref を自分自身の ref として公開できるようになります
フォワーディングを試す
子供のコンポーネントとして FancyButton
を用意した。
関数コンポーネントなので、通常では親からrefを渡すことはできない。これはDOM同士を依存させないためのReactの仕様となる
とはいえ、様々な箇所で再利用可能なボタンやinputコンポーネントを作成する場合、refをとれたほうが都合がよい場合が多い。
const RefChild = () => {
const ref = useRef<HTMLButtonElement>(null!)
const catchRef = () => {
console.log(ref.current) // FancyButton
}
return (
<>
<button onClick={catchRef}>親ボタン</button>
<FancyButton ref={ref} type="submit"><span>子供ボタン</span></FancyButton>
</>
)
}
type FancyButtonElementType = HTMLButtonElement | null
type FancyButtonProps = JSX.IntrinsicElements['button']
const FancyButton = forwardRef<FancyButtonElementType, FancyButtonProps>((
props,
ref
) => {
return (
<div>
<button ref={ref} data-fancy='fancy2'{...props} />
</div>
)
})
FancyButton.displayName = 'FancyButton'
下記スクショの通り、親ボタン押下にて、子コンポーネントのbuttonの情報を取得できた。
forwardRef の型に関しての理解はもっと深める必要あり。