はじめに
これまでid属性の重複を嫌って、htmlを書くときはidを極力使わないようにしてきた。しかし、React18のリリースにあたってuseIdが使えるようになり、ハイドレーション時にクライアント・サーバー間で一意なidを割り振ることができるようになった。そのためReact18以降を用いる場合はid属性が重複する問題がなくなった(書き方によっては重複する)。この記事ではuseIdの紹介と、useIdを使用した簡単な例を紹介する。
useIdとは
useIDはReact18のリリースで追加されたフックAPIの一つで、useTransitionなどと同時に追加されたものである。
機能自体は簡潔で公式に書かれていることに尽きる。
useId はハイドレーション時の不整合を防ぎつつサーバとクライアント間で安定な一意 ID を作成するためのフックです。
useIdを呼び出すと:r0:
や:ra:
のように:
で挟んだような文字列が生成される。
// 関数コンポーネントのトップレベルで実行
const id = useId()
console.log(id) // :r0:
1ページに複数のルートがある場合はIDの重複が起きるのでそれを防ぐためにcreateRoot
やhydrateRoot
の段階で第二引数のoptionsにidentifierPrefixを設定することができる。ちなみにReactDOMのrenderはReact18ではサポートされておらず、createRoot
などを使う必要があります(詳細はこちら)。
const container = document.getElementById('root')
const root = ReactDOM.createRoot(
container,
{
identifierPrefix: 'vv'
}
)
このように設定することで、:r0:
となるはずだったIDは:vvr0:
となる(与えた文字列がprefixになる)。
※:
が含まれるためCSSセレクタやquerySelectorAllで使用することはできません。
※配列によって生成した要素のkeyとして与えることはかえってパフォーマンスが下がるのでやめましょう(なぜなのか知りたい場合は差分検出処理を読んでください)。
例
簡単な例としてinputフィールドを紹介する。labelとinputの紐付けとaria-errormessageの設定、この二つの場面でidを使用したコードを紹介する。aria-errormessageについて詳細は述べないが、他のWAI-ARIAにもidを使用する属性もあるのでそれらにも使えるだろう。これらのa11yを考慮したwebサイトの構築はReactも全面的にサポートを行なっているので是非積極的に導入していただきたい。
今回紹介する例のコードはこちら
See the Pen useIdInput by KokiSakano (@kokisakano) on CodePen.
ボタンを押すことでエラーの表示非表示を変更できるだけのシンプルなページである。
labelのhtmlFor
とinputのid
はuseIdによって生成したIDによって紐づけることができ、inputのaria-errormessage
はp(エラー文)のid
と別に生成したuseIdと紐づけることができている。
レンダリング部分(25行目以降)は基本的に教科書通りの設定をしているが、createRoot
を呼び出す際は第二引数のoptionsにidentifierPrefix
を設定した。こうすることでuseIdによって生成される文字列にprefixを与えることができる。この例はrootが単一なので設定する必要がないが、例として書いた。
おわりに
useIdはシンプルに書けて特に解説する部分もないので例の説明もコンパクトなものになった。それだけシンプルなhookを使うことでクライアント・サーバー間で一意なIDを生成することができるので、これまでhtmlのid要素を使うことを避けていた人も使用してみるのはいかがだろうか。