ここまでで、実務で使うフックはほぼ出そろいました。この回は残りを片づけます。
すべてを覚える必要はありません。「名前と、どういうときに出てくるか」が分かっていれば、必要になったときに調べられます。
useId——重複しないidを作る
フォームを書くと必ず必要になります。
const id = useId()
<label htmlFor={id}>名前</label>
<input id={id} /><label>と<input>はhtmlForとidでつなぎます。ところがその部品を同じ画面に2つ置いた瞬間、idが重複します。重複すると、ラベルを押しても後ろのほうにフォーカスが行きません。
実際にuseId()が返した値を見ると、_r_0_・_r_1_のように呼ばれるたびに違う値になっていました。同じ部品を2つ置いても衝突しません。
複数の欄があるときは、接尾辞を足して1つのuseIdを使い回すのが定番です。
const id = useId()
<input id={`${id}-name`} />
<input id={`${id}-area`} />useLayoutEffect——描かれる前に測る
useEffectは画面に描かれたあとに走ります。ふだんはそれで困りません。
困るのは測ってから位置を直すときです。useEffectだと「一瞬ずれた状態が見えてから、直る」——つまりちらつきます。
const boxRef = useRef(null)
const [width, setWidth] = useState(0)
useLayoutEffect(() => {
setWidth(boxRef.current?.getBoundingClientRect().width ?? 0)
}, [])useLayoutEffectは描かれる直前に同期的に走るので、ずれた状態が表示されません。実際に測ると、最初の表示の時点でwidth: 1216が入っていました。
| 走るタイミング | 使うとき | |
|---|---|---|
useEffect | 画面に描かれたあと | ふつうはこちら。通信・購読・タイマー |
useLayoutEffect | 描かれる直前(同期) | 測って、その場で位置を直す(ツールチップ・吹き出し) |
useImperativeHandle——部品の外に操作を公開する
refで渡ってくるのは、ふつうDOMそのものです。自分で作った操作を渡したいときに使います。
function Modal({ ref }) {
const dialogRef = useRef(null)
useImperativeHandle(ref, () => ({
open: () => dialogRef.current?.showModal(),
close: () => dialogRef.current?.close(),
}))
return <dialog ref={dialogRef}>…</dialog>
}親からはmodalRef.current?.open()と書けます。DOM全部ではなく、決めた操作だけを外に出すのがねらいです。
useSyncExternalStore——Reactの外の値を購読する
Reactの外にある値をコンポーネントで使うためのフックです。
function useIsOnline() {
return useSyncExternalStore(
(callback) => {
window.addEventListener('online', callback)
window.addEventListener('offline', callback)
return () => {
window.removeEventListener('online', callback)
window.removeEventListener('offline', callback)
}
},
() => navigator.onLine, // いまの値
() => true, // サーバー側での値
)
}引数は購読する関数・値を読む関数・サーバー側で読む関数の3つです。
自分で書く機会はそう多くありませんが、知っておく価値はあります。状態管理ライブラリの回で入れたZustandは、内部でこれを使ってストアとReactをつないでいます。「Providerが無いのに再描画される」仕組みの正体がこれです。
全体の早見表
ここまでで出てきたフックをまとめます。
| フック | 何のため | 出た回 |
|---|---|---|
useState | 画面に出す値を持つ | state |
useEffect | 外の世界と同期する | effect |
useContext | 深いところへ値を配る | context |
useRef | DOMの操作・覚えておくだけの値 | refs-and-portals |
useMemo / useCallback | 計算と関数を覚えておく | rendering |
useReducer | 複雑なstateの変え方をまとめる | use-reducer |
useId | 重複しないidを作る | この回 |
useLayoutEffect | 描かれる前に測って直す | この回 |
useImperativeHandle | 部品の操作を外に公開する | この回 |
useSyncExternalStore | Reactの外の値を購読する | この回 |
useTransition / useDeferredValue | 優先度を下げる | react19 / large-lists |
useActionState / useOptimistic | フォームの送信と先出し表示 | react19 |
use | Promiseやcontextを読む | react19 |
毎日使うのは上の4つだけです。残りは「そういうものがある」と知っていれば十分で、それがこの回の目的です。
Reactカスタムフックにまとめるカスタムフックの回。ここに出てきたフックも、まとめて自分のフックに包めます公式ドキュメントも見てみる
ja.react.dev外部サイト組み込みの React フック – ReactReact公式のフック一覧。この回で扱ったものも含めて、すべてのフックがここから引けますこのレッスンのまとめ
useIdは重複しないidを作る。<label htmlFor>と<input id>をつなぐのに必須Math.random()で代用しない(描き直しで変わる・サーバー側とずれる)useLayoutEffectは描かれる直前に同期で走る。測って直すときだけ- 既定は
useEffect。useLayoutEffectは表示を遅らせる useImperativeHandleは部品の操作を外に公開する。まずpropsで足りないか考えるuseSyncExternalStoreはReactの外の値を購読する。Zustandの中身がこれ- 毎日使うのは
useState・useEffect・useContext・useRef。残りは名前を知っていれば十分
次は、エラーで画面全体が消えないようにする回です。