logo

useIdでアクセシビリティ属性のための一意のIDを生成する

2025-11-20
a month ago

開発環境

  • react 19.2.0
  • react-dom 19.2.0

前提

アクセシビリティを担保するうえで id 属性は不可欠です。

特に <label><input> の関連付け、aria-describedby などは「一意の ID」が求められます。

しかしコンポーネントが複数回レンダーされたり、SSR と CSR で一致したりする必要がある場合、単純にランダム ID を生成すると不整合が起きることがあります。

この問題を安全に解決するために React が提供しているのが useId です。

本題

useId の要点

公式ドキュメントから要点だけ抜き出すと以下になります。

  1. クライアント / サーバーで ID が安定する(SSR 環境向け)
  2. コンポーネントごとに衝突しない一意の値を生成
  3. プレフィックスを追加して複数 ID を派生させられる
  4. フォーム・ARIA 属性に最適

特にサーバーサイドレンダリング(Next.js 等)では、「サーバーで生成した HTML とクライアントの初期レンダーで ID が一致する」ことが重要で、useId はこれを保証します。

基本的な使い方

最も代表的な例は <label><input> の関連付けです。

import { useId } from 'react';

function NameField() {
  const id = useId();

  return (
    <div>
      <label htmlFor={id}>名前</label>
      <input id={id} type="text" />
    </div>
  );
}

生成される ID は React が内部的に管理するため衝突の心配がありません。


👉 プレフィックスで ID を派生させる

同じ useId() を基点に複数の ID を生成でき、一覧系のフォームでも安全に使えます。

import { useId } from 'react';

function ProfileForm() {
  const baseId = useId();

  return (
    <section>
      <div>
        <label htmlFor={`${baseId}-name`}>名前</label>
        <input id={`${baseId}-name`} />
      </div>

      <div>
        <label htmlFor={`${baseId}-email`}>メール</label>
        <input id={`${baseId}-email`} />
      </div>
    </section>
  );
}

baseId の前後に任意の文字列を付けるだけで複数の ID を安全に生成できます。


👉 aria 属性に利用する例 aria-describedby との組み合わせもよく使われます。

import { useId } from "react";

function PasswordInput() {
  const id = useId();
  const descriptionId = `${id}-desc`;

  return (
    <div>
      <label htmlFor={id}>パスワード</label>
      <input id={id} type="password" aria-describedby={descriptionId} />
      <p id={descriptionId}>8文字以上で入力してください</p>
    </div>
  );
}

スクリーンリーダーが説明文を正しく参照できるようになります。


👉 繰り返しコンポーネントの例 リストやモーダル内でコンポーネントが複数レンダーされても ID が衝突しません。

function TodoItem({ todo }) {
  const id = useId();

  return (
    <div>
      <input id={id} type="checkbox" />
      <label htmlFor={id}>{todo.title}</label>
    </div>
  );
}

function TodoList({ items }) {
  return (
    <div>
      {items.map(item => (
        <TodoItem key={item.id} todo={item} />
      ))}
    </div>
  );
}

手動でユニーク ID を作る必要がなくなり、保守性が向上します。

さいごに

useId は「アクセシビリティ属性用に一意 ID を安全に生成する」ことに特化したフックで、特に SSR 環境や複数レンダーされる UI で効果を発揮します。

  • ID の衝突を防ぐ
  • SSR / CSR で ID がズレない
  • label/input や aria 系属性に最適

React が提供する標準フックとして扱いやすく、フォームやアクセシビリティを強化するうえで必須となる場面が多いです。

参照