LoginSignup
0
1

Reactのアクセシビリティ改善に役立つユニークIDの生成

Last updated at Posted at 2024-02-24

React 18に追加された新しいフック useId を活用することで、重複やハイドレーションエラーを起こさずにユニークなIDを生成する方法を解説します。

(React 19を使用しています)

※ これは2022/12/4に個人ブログで公開した記事を移植し、CC0-1.0で提供しています。情報は古い可能性があります。

ユニーク ID の必要性

アクセシビリティを改善するためにHTML AttributeへIDを指定することがよくあります。

  • 固定値を設定した場合、同じコンポーネントが複数レンダリングされた場合に、IDが重複してしまいます。
  • 乱数にした場合、生成されたHTMLとハイドレーション時のIDが異なることにより整合性が取れないためパフォーマンスの問題が発生してしまいます。

useId について

これらの問題を解決するために、React 18で新しいフック useId が登場しました。

useId はハイドレーション時の不整合を防ぎつつサーバとクライアント間で安定な一意 ID を作成するためのフックです。

使用方法

公式ドキュメントによると、1つのコンポーネントで複数のIDを使う場合、接尾辞を付けるよう記載がありました。

  • labelタグのforでinputを指定する
  • バリデーションエラーをWAI-ARIAで指定する

場合次のようになります。

import { useId } from "react";

const PasswordInput = () => {
  const id = useId();
  const inputId = id + "_input";
  const errorMessageId = id + "_errorMessage";

  return (
    <>
      <label htmlFor={inputId}>パスワード</label>
      <input
        id={inputId}
        type="password"
        autoComplete="current-password"
        value={props.value}
        onChange={props.onChange}
        aria-invalid={props.hasError}
        aria-errormessage={props.errorMessageId}
      />
      {props.errorMessage !== undefined && (
        <span id={errorMessageId}>{errorMessage}</span>
      )}
    </>
  );
};

単体テストの書き方

恥ずかしながら今まで1つしかレンダリングされない前提で、IDを定数で実装していました。テストもその形で作っていたので動的なIDの場合に取得する方法がわからず、しばらくtesting-libraryのドキュメントを探し回っていました。

結果として、 @testing-library/jest-dom の便利マッチャーを使うとシンプルで宣言的にテストを書くことが出来ました。

(jest 29, jest-dom 5を使用しています)

describe("Password", () => {
  // ...
  describe("has error", () => {
    // ...
    test("has error message", () => {
      // ...
      expect(passwordInput).toBeInvalid();
      expect(passwordInput).toHaveErrorMessage(
        "ID またはパスワードが誤っています",
      );
    });
  });
});

まとめ

  • ID系のHTML Attributeを追加したい場合は useId を使ってみよう
  • @testing-library/jest-dom 便利
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1