そもそも「Ref」って?
どんな時に使うかというとReact.jsでの開発時、DOMに直接アクセスしたい時に使用します。
React.jsでは原則的に仮想DOMを通してのDOMを書き換えていくので、Refというのはいわば邪道です。
Reactの標準ライブラリであるuseRef() を使うことでrefを使用することができます。
DOMに直接アクセスして何かしたいというケースは少ないですが、例えば
- ボタンを押した時、特定のコンポーネントの位置まで自動でスクロールしたい時
- 画面に訪れたタイミングで、特定のInputフォームにfocusを当てたい時
- videoタグのplay・pauseメソッドを使いたい
などなど...
forwardRefとは
例えば、親コンポーネントで定義してるRefをpropsで子コンポーネントに渡して、そっち側で利用したい時があったとします。
しかし通常、コンポーネントでは親からRefを引数として受け取ることができません。
そこでforwardRefを使用することで、親から子にRefを渡すことができるようになります。
forwardRefとはコンポーネントが別のコンポーネントのDOMにアクセスしたい時に使うためのものです。
実際の使い方
こう書くとエラーになる
以下のように書くと一見、子コンポーネントのSubmitButtonにrefが渡ったかのように見えますが、実際はエラーになります。
// 親コンポーネント
const Home = () => {
const newRef = useRef()
return (
<div>
<SubmitButton ref={newRef}/>
</div>
)
}
// 子コンポーネント
const SubmitButton = ({ref}) => {
return (
<button onClick={() => console.log({ref})}></button>
)
}
「refはpropsではないです。もしアクセスしたいのであれば別の方法でアクセスしてください」
「React.forwardRef()を使うつもりでしたか?」
とwarnningが出てきました。
forwardRefを使っての正しい方法
// 親コンポーネント
const Home = () => {
const newRef = useRef()
return (
<div>
<SubmitButton ref={newRef}/>
</div>
)
}
// 子コンポーネント
const SubmitButton = forwardRef(function SubmitButton(props, ref) {
return (
<div>
<button onClick={() => console.log(ref)}>送信</button>
</div>
)
})
無事、親コンポーネントからrefの値を受け取ることができました。
これを流用することで、さらに下のコンポーネントにバケツリレーでrefを渡すことも可能です。
最後に
基本的にReactの開発でRefの多用は推奨されてないため、極力使わない方法での実装が好ましいです。
というより大体のことはRefを使用しなくても実装できます。
以下公式ドキュメント