The useId hook generates unique, stable ID strings that remain consistent across client-side and server-side rendering (SSR), avoiding hydration mismatch errors in React applications.
useId is designed primarily for building accessible HTML form components where input controls require matching label htmlFor attributes or ARIA accessibility identifiers (aria-describedby).
import React, { useId } from 'react';
export default function AccessibleInputField({ label, type = 'text', hintText }) {
// Generate unique IDs stable across SSR hydration
const inputId = useId();
const hintId = useId();
return (
<div className="form-group">
<label htmlFor={inputId}>{label}</label>
<input
id={inputId}
type={type}
aria-describedby={hintText ? hintId : undefined}
/>
{hintText && (
<span id={hintId} className="hint-text">
{hintText}
</span>
)}
</div>
);
}
useId for Multiple Sibling ElementsTo generate unique IDs for multiple related elements within a single component, prefix or suffix the returned ID string:
export default function RegistrationGroup() {
const baseId = useId();
return (
<form>
<label htmlFor={`${baseId}-first`}>First Name</label>
<input id={`${baseId}-first`} type="text" />
<label htmlFor={`${baseId}-last`}>Last Name</label>
<input id={`${baseId}-last`} type="text" />
</form>
);
}
useId to Generate Keys in Lists: useId is NOT meant for list item key attributes. Keys in .map() loops should be derived from your dataset's persistent IDs (item.id).Math.random(), useId generates identical ID strings on both the Node.js server renderer and the client browser during hydration.Why does using Math.random() to generate DOM element IDs cause hydration errors in server-side rendered React applications?
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With