useId renvoie un identifiant unique pour chaque instance d'un composant, et le même identifiant à chaque rendu. Utilisez-le pour relier un <label> à son <input>, ou un champ à son aide via aria-describedby, quand le composant peut apparaître plus d'une fois sur une page.
Le même composant s'affiche deux fois et reçoit deux ids différents, affichés sous chaque champ. Cliquez sur le texte "Confirm password" et le focus passe au second champ, car son htmlFor ne correspond qu'à l'id de ce champ. Écrivez en dur id="password" à la place de useId() et les deux labels désignent le premier champ.
La syntaxe
const id = useId();
useId ne prend aucun argument et renvoie une chaîne. Appelez-le au niveau supérieur du composant, comme tous les hooks. Son format exact est interne et a changé entre les versions : React 18 produisait :r1:, et React 19.2 produit _r_1_ pour un composant rendu d'abord dans le navigateur et un id commençant par _R_, construit à partir de la position dans l'arbre, pour un composant rendu sur le serveur. Ne l'analysez jamais et ne comptez pas sur sa forme.
Pourquoi pas Math.random ou un compteur
Les ids d'accessibilité doivent correspondre entre le HTML envoyé par le serveur et l'arbre que React construit dans le navigateur. Les deux façons évidentes de créer un id échouent toutes deux à ce test.
// Changes on every render, and differs between server and browser
const id = 'field-' + Math.random().toString(36).slice(2);
// The server's counter keeps growing across requests, the browser starts at 0
let nextId = 0;
const id = 'field-' + nextId++;
Avec le rendu serveur (Next.js, le mode framework de React Router, toute configuration avec hydrateRoot), le serveur écrit id="field-4817" dans le HTML, le premier rendu du navigateur calcule field-0, et React signale une erreur d'hydratation. useId construit l'id à partir de la position du composant dans l'arbre, identique des deux côtés.
Même sans serveur, un id construit pendant le rendu peut changer à chaque rendu. Cet exemple montre la différence sans aucun serveur :
Cliquez plusieurs fois sur le bouton. La valeur de useId ne bouge pas, tandis que l'id du compteur augmente à chaque rendu, donc tout ce qui désignait l'ancien id (un aria-describedby, un label) ne désigne plus rien. Envelopper le compteur dans useState(() => nextId++) réglerait les nouveaux rendus, mais pas l'incohérence avec le serveur.
Plusieurs ids avec un seul appel
Un composant avec plusieurs champs n'a pas besoin de plusieurs appels à useId. Générez une base et ajoutez un suffixe par élément.
Tapez un mot sans @ dans le champ email : l'erreur apparaît et le aria-describedby du champ la désigne, donc un lecteur d'écran lit l'erreur quand le champ reçoit le focus. Affichez <SignupForm /> deux fois dans App et chaque copie reçoit sa propre base d'id.
Pas pour les keys de liste
Les keys et les ids résolvent des problèmes différents. Une key indique à React quel élément est lequel d'un rendu à l'autre, elle doit donc venir des données. useId donne un id par instance de composant, et vous ne pouvez pas l'appeler dans map.
// Wrong: breaks the rules of hooks, and the key is unrelated to the item
{todos.map((todo) => <Todo key={useId()} todo={todo} />)}
// Right: the key comes from the data
{todos.map((todo) => <Todo key={todo.id} todo={todo} />)}
Quand vos données n'ont pas d'identifiant, créez-en un à la création de l'élément (crypto.randomUUID() dans le gestionnaire d'événement qui l'ajoute), pas pendant le rendu. La page sur les listes et les keys explique pourquoi la key doit rester avec son élément.
Plusieurs racines React sur une même page
Si deux applications React distinctes s'affichent sur la même page, leurs ids pourraient entrer en collision. Donnez un préfixe à chaque racine :
createRoot(document.getElementById('cart'), { identifierPrefix: 'cart-' });
createRoot(document.getElementById('chat'), { identifierPrefix: 'chat-' });
Avec le rendu serveur, passez le même identifierPrefix au moteur de rendu serveur et à hydrateRoot pour que les deux côtés produisent les mêmes ids.
Erreurs courantes
Afficher un arbre différent sur le serveur et dans le navigateur. useId dépend de la position du composant, donc une branche comme typeof window === 'undefined' ? <A /> : <B /> au-dessus d'un champ peut décaler les ids entre les deux rendus. Gardez le même arbre pendant l'hydratation et changez ensuite, dans un effet.
Chercher l'élément par son id. document.getElementById(id) fonctionne, mais une ref est la façon React d'atteindre un nœud DOM et ne nécessite aucun id.
L'utiliser comme valeur aléatoire. L'id est unique dans l'application, pas aléatoire, et il est prévisible à partir de l'arbre. Ne l'utilisez pas pour des jetons de sécurité, des clés de cache ou quoi que ce soit stocké d'une session à l'autre.
Quand l'utiliser
Utilisez useId chaque fois qu'un composant réutilisable a besoin d'un attribut id : des champs de formulaire construits à partir d'un composant utilisé plusieurs fois, une infobulle reliée par aria-describedby, une boîte de dialogue avec aria-labelledby, des onglets avec aria-controls. Quand un id ne fait que relier un label à son champ, vous pouvez aussi vous passer d'id et placer le champ dans le label (<label>Name <input /></label>) ; utilisez useId quand les éléments ne peuvent pas être imbriqués.
Questions fréquentes
Que fait useId dans React ?
Il renvoie une chaîne unique pour cette instance de composant, qui reste la même à chaque rendu. Vous l'utilisez pour relier des éléments par id : htmlFor sur un label, aria-describedby sur un champ, aria-labelledby sur une boîte de dialogue.
Pourquoi ne pas utiliser Math.random() ou un compteur pour les ids ?
Ils donnent des valeurs différentes sur le serveur et dans le navigateur, donc une page rendue par le serveur et sa version hydratée ne concordent pas et React signale une erreur d'hydratation. Math.random() change aussi à chaque rendu. useId dérive l'id de la position du composant dans l'arbre, qui est la même aux deux endroits.
Peut-on utiliser useId pour les keys d'une liste ?
Non. Une key doit venir de vos données pour que React puisse associer le même élément d'un rendu à l'autre. useId est appelé une fois par composant, et l'appeler dans map enfreint de toute façon les règles des hooks. Utilisez l'identifiant propre de l'élément.
Comment obtenir plusieurs ids avec un seul appel à useId ?
Appelez useId une fois et ajoutez des suffixes : ${id}-name, ${id}-email. La base est unique, les chaînes suffixées le sont donc aussi.
Peut-on utiliser l'id de useId dans un sélecteur CSS ?
Évitez-le. L'id sert à relier des éléments dans le DOM, et son format exact est un détail interne qui a changé entre les versions de React. Stylisez avec une classe, et trouvez les éléments avec une ref plutôt qu'avec querySelector.