Capítulo 55 de 116

Chapter 55: useId

Core Idea

useId() generates a stable, unique-per-component-instance ID string safe to use for accessibility attributes (linking a label to an input) — specifically designed to match between server and client rendering, unlike a manually incremented counter.

Key Concepts

  • Signature: const id = useId() — no arguments, returns a string unique to that Hook call within the app, stable across re-renders of the same component instance.
  • Why not just a counter/random number? A hand-rolled incrementing counter or Math.random() produces different values on the server vs. the client during SSR hydration, causing a mismatch error — useId is specifically built to generate identical IDs on both sides.
  • Not for list keys. useId generates one ID per Hook call, not per data item — using it as a substitute for a proper data-derived key (Ch 17) is a misuse; keys must come from your data.
  • Prefixing for multiple related IDs: when one component needs several related IDs (a form with multiple field/label pairs), generate one useId() call and derive suffixed variants from it (e.g. `${id}-firstName`) rather than calling useId() once per field, keeping them visibly grouped.
  • Shared ID prefix across an app: createRoot/hydrateRoot accept an identifierPrefix option so IDs generated by useId don't collide when multiple independent React roots exist on the same page.

Code Examples

function PasswordField() {
  const id = useId();
  return (
    <>
      <label htmlFor={id}>Password:</label>
      <input id={id} type="password" />
    </>
  );
}
  • What it demonstrates: linking a <label> to its <input> via a generated, SSR-safe id — the canonical use case.

Key Takeaways

  1. Use useId specifically for accessibility-relevant DOM IDs (label/input associations, aria-describedby targets) — not for list keys, not as a general unique-ID utility.
  2. It's the only ID-generation approach guaranteed to match between server-rendered and client-hydrated output.
  3. For multiple related IDs in one component, call it once and derive suffixes, rather than calling it repeatedly.

Connects To

  • Ch 17 (Rendering Lists): the correct source of key values, which useId is not.
  • Ch 94-95 (createRoot / hydrateRoot): where the identifierPrefix option lives for multi-root pages.