useRefで作った値は、どのプロパティに保存されている?
解説
useRefが返すのは{ current: 初期値 }というシンプルなオブジェクト。値の読み書きはすべて.currentプロパティを通じて行う。.valueや.refといったプロパティは存在しない。.stateはいかにもReactっぽいが、これもuseRefには関係ない。実際のコードで見ると次のようになる。const countRef = useRef(0); console.log(countRef.current); // 0 countRef.current = 5; console.log(countRef.current); // 5このように.currentに直接代入するだけで値を更新できる。useStateのようにセッター関数を呼ぶ必要はない。なぜ直接値を返さず、オブジェクトで包んでいるのか「useRef(0)が0をそのまま返してくれればいいのに」と感じるかもしれないが、JavaScriptではプリミティブ値(数値・文字列・booleanなど)は代入時にコピーされる。もしuseRefが生の値を返したら、再レンダリング時に新しい変数にコピーされるだけで、元の値を書き換える手段がなくなる。オブジェクトで包むことで参照が維持され、.currentを書き換えれば常に同じオブジェクトの中身が変わる。これが「ref(参照)」という名前の由来でもある。DOM要素を扱うときも.currentuseRefはDOM要素への参照を取得する場面でもよく使われるが、アクセス方法は同じく.current。const inputRef = useRef(null); const handleClick = () => { inputRef.current.focus(); // .currentがDOM要素を指す }; return <input ref={inputRef} />;ref属性にrefオブジェクトを渡すと、ReactがマウントのタイミングでそのDOM要素を.currentに自動で代入してくれる。アンマウント時にはnullに戻る。Vueの ref() との混同に注意Vueを触ったことがある人はref()の.valueと混同しやすい。Vue のref()は.valueでアクセスするが、ReactのuseRefは.current。フレームワークを行き来するときに地味にハマるポイントなので、「Reactは.current」と覚えておくとよい。