React で子コンポーネントを ref で触りたい時、forwardRef APIを使うように言われます。
例えばボタンをクリックしたらフォーカスされるインプットフィールドだとこんな感じ。
import React, { useRef } from 'react'; const InputField = React.forwardRef({placeholder}, ref) => { return <input ref={ref} placeholder={placeholder} /> }); const App = () => { const inputRef = useRef(null); const onFocus = () => { inputRef.current.focus(); }; return ( <> <InputField ref={inputRef} placeholder={forwardRef Input Field} /> <button onClick={onFocus}>Focus</button> </> ); };
ref という名前で渡さなければ forwardRef API を使わなくても問題なく動作する
forwardRef を使わずに ref={ref}
のような props を渡していると Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
という warning が発生するのですが、子コンポーネントに渡す props のキーが ref
という名前でなければ warning も発生せず問題なく動作してしまうみたいです。
import React, { useRef } from 'react'; const InputField = ({placeholder, elmRef}) => { return <input ref={elmRef} placeholder={placeholder} /> }; const App = () => { const inputRef = useRef(null); const onFocus = () => { inputRef.current.focus(); }; return ( <> <InputField elmRef={inputRef} placeholder={Input Field without forwardRef} /> <button onClick={onFocus}>Focus</button> </> ); };
forwardRef API を使った方が速いとかあるのでしょうか?
チョット判らないのですが、これでも forwardRef を使った時と同じように問題なく動作します。
サンプル
See the Pen React forwardRef vs useRef by KIKIKI (@kikiki_kiki) on CodePen.
TypeScript だと渡される props は RefObject
なのでこんな感じ
import React, { useRef, RefObject } from 'react'; type InputFieldProps = { placeholder: string; elmRef: RefObject<HTMLInputElement> }; const InputField = ({placeholder, elmRef}: InputFieldProps) => { return <input ref={elmRef} placeholder={placeholder} /> }; const App = () => { const inputRef = useRef<HTMLInputElement>(null); const onFocus = () => { inputRef.current && inputRef.current.focus(); }; return ( <> <InputField elmRef={inputRef} placeholder={Input Field without forwardRef} /> <button onClick={onFocus}>Focus</button> </> ); };
おわり

React Hooks TypeScript 実践入門 - Firebase を使って素材配布サイトを作ろう! (プログラミング実践入門)
- 作者:Yoshiki Mogi
- 発売日: 2020/04/23
- メディア: Kindle版