🐼

【React 公式の旅 #1】useId() がちょっと便利そう

2024/03/21に公開

意図

Reactの公式サイトで使ったことがないものがあったので試してみる

useId は、アクセシビリティ属性に渡すことができる一意の ID を生成するための React フックです。

なんかIDを作成してくれるらしい。
こんな感じでuseId()をつかばReactが良さげなIDを作成してくれるという。

実践

App.tsx
import { useId } from 'react'

const uid = useId()

というわけでコンソールでどんな値が取れるのか試してみよう。

なんかIDっぽいやつが取れた。
しかもロードしても同じ値だったのでランダムっていう感じでもない。
まじでどこで使うのかわからんので公式を読み進めてみよう。

App.tsx

import { useId } from "react";
import "./App.css";

function App() {
  const passwordHintId = useId();

  return (
    <>
      <input type="password" aria-describedby={passwordHintId} />
      <p id={passwordHintId}></p>
    </>
  );
}

export default App;

こんな感じの場合inputとpグループ化できるのでアクセシビリティ的に良くなるとのこと。
aria-describedbyの説明も公式に書いてあるのは優しい

でもふと思う。普通にID直で書いたらよくね??と
そう思っていたらReactがそう思ってんだろ?と言って来てるかのごとく論破してきた。

ID をハードコードすることは、React ではおすすめできません。コンポーネントはページ上で複数回レンダー可能ですが、ID は一意である必要があります! ID をハードコードするのではなく、useId を使用して一意の ID を生成します。

直書きはおすすめしないらしい
その理由もしっかりとコードを持って説明してくれた

App.tsx

import { useId } from 'react';

function PasswordField() {
  const passwordHintId = useId();
  return (
    <>
      <label>
        Password:
        <input
          type="password"
          aria-describedby={passwordHintId}
        />
      </label>
      <p id={passwordHintId}>
        The password should contain at least 18 characters
      </p>
    </>
  );
}

export default function App() {
  return (
    <>
      <h2>Choose password</h2>
      <PasswordField />
      <h2>Confirm password</h2>
      <PasswordField />
    </>
  );
}

ここでようやく納得がいった。
そりゃ同じページに同じIDが複数あったらいかんでしょうと、、、、、、
そういうことか。ってHTMLの基礎中の基礎やないかい!

結論としてはコンポーネント複数回呼んでもIDが被りませんよってことね。
いやもっと簡単に説明できるだろ!!!

今後の改善

今まで自分の書き方で改善できそうなところがあったので試してみる。

今までの書き方

App.tsx

import { useId } from 'react';

function LabelWithInput({ id }: {id:string}) {
  const passwordHintId = useId();
  return (
    <>
      <label htmlFor={id}> 
        Password:
        <input
          id={id}
          type="text"
          aria-describedby={passwordHintId}
        />
      </label>
      <p id={passwordHintId}>
        The password should contain at least 18 characters
      </p>
    </>
  );
}

export default function App() {
  return (
    <>
      <LabelWithInput id="name" />
      <LabelWithInput id="name_kana" />
    </>
  );
}

useIdを理解してるともっと簡易的にかける。
いままでpropsで渡していたものがその必要性がなくなり楽に書けるようになった。

App.tsx

import { useId } from 'react';

function LabelWithInput() {
  const passwordHintId = useId();
  const inputId = useId()
  return (
    <>
      <label htmlFor={inputId}> 
        Password:
        <input
          id={inputId}
          type="text"
          aria-describedby={passwordHintId}
        />
      </label>
      <p id={passwordHintId}>
        The password should contain at least 18 characters
      </p>
    </>
  );
}

export default function App() {
  return (
    <>
      <LabelWithInput  />
      <LabelWithInput  />
    </>
  );
}

まとめ

公式を見てると新たな発見や自分の未熟さがわかるので一日一個くらい見たことないものを試していきたい。

Discussion