【React 公式の旅 #1】useId() がちょっと便利そう
意図
Reactの公式サイトで使ったことがないものがあったので試してみる
useId は、アクセシビリティ属性に渡すことができる一意の ID を生成するための React フックです。
なんかIDを作成してくれるらしい。
こんな感じでuseId()をつかばReactが良さげなIDを作成してくれるという。
実践
import { useId } from 'react'
const uid = useId()
というわけでコンソールでどんな値が取れるのか試してみよう。
なんかIDっぽいやつが取れた。
しかもロードしても同じ値だったのでランダムっていう感じでもない。
まじでどこで使うのかわからんので公式を読み進めてみよう。
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 を生成します。
直書きはおすすめしないらしい
その理由もしっかりとコードを持って説明してくれた
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が被りませんよってことね。
いやもっと簡単に説明できるだろ!!!
今後の改善
今まで自分の書き方で改善できそうなところがあったので試してみる。
今までの書き方
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で渡していたものがその必要性がなくなり楽に書けるようになった。
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