useId generates a stable, unique string ID for a component instance that matches identically on both the server and the browser client. Hardcoding id="email" breaks accessibility whenever a form component renders twice on the same page, whereas Math.random() causes server-client hydration mismatches in SSR frameworks like Next.js.
Call useId() once per component and derive related field IDs by appending suffixes such as ${id}-input and ${id}-hint. This guarantees valid HTML associations for screen readers without inventing random numbers.
import { useId } from 'react';
export function PasswordField({ label, hint }) {
const baseId = useId();
const inputId = `${baseId}-password`;
const hintId = `${baseId}-hint`;
return (
<div className="field-group">
<label htmlFor={inputId}>{label}</label>
<input
id={inputId}
type="password"
aria-describedby={hintId}
/>
<p id={hintId} className="field-hint">
{hint}
</p>
</div>
);
}
useId Beats Math.random()In Server-Side Rendering (Next.js or Remix), the server renders HTML first and sends it to the browser for hydration. Math.random() produces a different value on the server than on the client, triggering React hydration warnings. useId derives IDs deterministically from the component's position in the React tree, guaranteeing a 100% match.
useId MistakesuseId for Array .map() Keys: Never write <li key={useId()}> or call useId() inside a loop. List keys must come from your underlying data IDs (item.id).useId Values Directly in CSS Selectors: React 19 IDs contain colons or special characters (such as :r1: or «r1»), which break unescaped document.querySelector('#...') calls.useId() separately for every input in one component?No. Call useId() once at the top of the component and append clear suffixes like ${id}-email and ${id}-zip for all fields inside that component.
useId strings stay identical across page refreshes?Yes, for the same rendered tree structure, though you should never persist useId values into a database or localStorage because tree changes alter them.
useId work in Client Components without SSR?Yes. Even in pure Vite single-page React apps, useId prevents duplicate HTML IDs whenever you render reusable form components multiple times on one screen.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With