useId は、アクセシビリティ属性を結び付けるための一意な ID を生成する Hook です。サーバー描画とクライアントの hydration でも同じ構造から整合した ID を作れます。
label と input を関連付ける
import { useId } from 'react';
function EmailField() {
const id = useId();
return <><label htmlFor={id}>メールアドレス</label><input id={id} type="email" /></>;
}
ページに EmailField を複数置いても、それぞれの呼び出しは別の ID を受け取ります。手で 'email' のような固定 ID を書くと label が意図しない input を指す可能性があるため、再利用可能なフォーム部品ほど useId が役立ちます。
同じコンポーネント内で複数の ID が必要なら、const hintId = ${id}-hint; のように共通の接頭辞から派生させます。aria-describedby と説明文の ID を結ぶ用途にも使えます。
label と input、エラーメッセージと aria-describedby のような関係が DOM 上で明示されると、スクリーンリーダー利用者が入力の目的と補足を把握できます。見た目だけ近くに置くより、属性で関係を表すことがアクセシビリティの基本です。
使わない場面
リストの key に useId を使ってはいけません。key はデータの同一性を表すため、データベース ID などデータ自身の安定した値を使います。また、各リスト要素で Hook を呼ぶ必要がある場合は、要素を子コンポーネントへ分けます。
複数の独立した React root を同じ HTML に描画する場合は、必要に応じて root ごとの identifierPrefix を設定します。これは ID 衝突を避けるためのアプリ基盤側の設定で、通常の単一 root の画面では意識する必要はありません。
ID をデータへ持ち出さない
useId の戻り値はコンポーネントのレンダー位置に基づく UI 用 ID です。保存した Todo の識別子、URL、テストデータの固定 selector として使うと、並び替えやレンダー構造の変更に弱くなります。データの identity とアクセシビリティ属性の ID は別の概念として扱います。
まとめ
useId は UI 部品の属性を安全に関連付ける ID のための Hook です。データ識別子や CSS セレクタの代用には使いません。