Hook useId
Gere um ID único e estável para atributos de acessibilidade que seja consistente entre servidor e cliente.
Busque em todas as páginas da documentação
Gere um ID único e estável para atributos de acessibilidade que seja consistente entre servidor e cliente.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Cartão de receita de referência rápida - pronto para copiar e colar.
const id = useId();
// Use para elementos de formulário acessíveis
<label htmlFor={id}>Email</label>
<input id={id} type="email" />
// Derive múltiplos IDs a partir de um
<label htmlFor={`${id}-first`}>Nome</label>
<input id={`${id}-first`} />
<label htmlFor={`${id}-last`}>Sobrenome</label>
<input id={`${id}-last`} />Quando usar: Você precisa de um ID único para htmlFor, aria-labelledby, aria-describedby, ou qualquer atributo DOM que exija um ID - especialmente em SSR ou componentes reutilizáveis.
"use client";
import { useId, useState } from "react";
interface TextFieldProps {
label: string;
helpText?: string;
}
export function TextField({ label, helpText }: TextFieldProps) {
const id = useId();
const helpId = `${id}-help`;
const [value, setValue] = useState("");
return (
<div className="space-y-1">
<label htmlFor={id} className="block text-sm font-medium">
{label}
</label>
<input
id={id}
value={value}
onChange={(e) => setValue(e.target.value)}
aria-describedby={helpText ? helpId : undefined}
className="border rounded px-3 py-2 w-full"
/>
{helpText && (
<p id={helpId} className="text-xs text-gray-500">
{helpText}
</p>
)}
</div>
);
}
export function SignupForm() {
return (
<form className="space-y-4 max-w-sm">
<TextField label="Email" helpText="Nunca compartilharemos seu e-mail." />
<TextField label="Senha" helpText="Pelo menos 8 caracteres." />
<TextField label="Nome de usuário" />
</form>
);
}O que isso demonstra:
TextField obtém seu próprio ID único de useId<label> a <input> via htmlFor e vincula o texto de ajuda via aria-describedbyuseId gera um ID baseado na posição do componente na árvore React: (por exemplo, :r1:) para evitar colisões com IDs definidos pelo usuáriouseId no mesmo componente produzem IDs diferentes| Parâmetro | Tipo | Descrição |
|---|---|---|
| (nenhum) | - | useId não recebe parâmetros |
| Retorno | Tipo | Descrição |
|---|---|---|
id | string | String de ID única (por exemplo, :r1:, :r2:) |
Listbox acessível:
function Listbox({ label, options }: ListboxProps) {
const id = useId();
const labelId = `${id}-label`;
const listId = `${id}-list`;
return (
<div>
<span id={labelId}>{label}</span>
<ul id={listId} role="listbox" aria-labelledby={labelId}>
{options.map((opt, i) => (
<li key={opt.value} id={`${id}-option-${i}`} role="option">
{opt.label}
</li>
))}
</ul>
</div>
);
}identifierPrefix personalizado para micro-frontends:
// Em createRoot ou hydrateRoot
const root = createRoot(container, {
identifierPrefix: "app1-",
});
// IDs gerados: ":app1-r1:", ":app1-r2:", etc.// useId sempre retorna uma string - nenhum genérico é necessário
const id: string = useId();
// Ao construir uma biblioteca de componentes, aceite um override opcional
interface InputProps {
id?: string;
label: string;
}
function Input({ id: propId, label }: InputProps) {
const generatedId = useId();
const inputId = propId ?? generatedId;
return (
<>
<label htmlFor={inputId}>{label}</label>
<input id={inputId} />
</>
);
}Não use para chaves de lista - useId gera um único ID por chamada de hook, não por item da lista. Não é adequado para props key. Correção: Use chaves baseadas em dados (item.id) ou identificadores estáveis para chaves de lista.
IDs contêm dois pontos - O formato do ID gerado (:r1:) inclui dois pontos, que são válidos em atributos id HTML, mas podem causar problemas com seletores CSS como #\:r1\:. Correção: Use seletores de atributo [id="valor"] ou escape os dois pontos em CSS.
Não pode ser usado condicionalmente - Como todos os hooks, useId não pode ser chamado dentro de condições ou loops. Correção: Chame useId no nível superior e derive sub-IDs com concatenação de strings.
Múltiplas raízes sem prefixo - Duas raízes React separadas na mesma página podem gerar IDs conflitantes. Correção: Use a opção identifierPrefix em createRoot ou hydrateRoot.
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
crypto.randomUUID() | Aplicativo apenas no cliente, sem SSR | SSR está envolvido - causa dessincronizações de hidratação |
| ID baseado em contador | Fora do React (funções utilitárias) | Dentro de componentes - não determinístico entre servidor/cliente |
useRef com inicialização preguiçosa | Você precisa de um valor aleatório estável, não um ID baseado na posição da árvore | Você precisa de atributos de acessibilidade seguros para SSR |
label HTML envolvendo | O rótulo envolve a entrada diretamente, nenhum id é necessário | A entrada e o rótulo estão separados no DOM |
Por que não usar apenas um ID aleatório? IDs aleatórios gerados durante a renderização diferem entre servidor e cliente, causando dessincronizações de hidratação e avisos do React. useId resolve isso derivando IDs da árvore de componentes.
useId deriva IDs da posição do componente na árvore React, então servidor e cliente produzem o mesmo ID.useId sempre que SSR estiver envolvido.useId gera um ID por chamada de hook, não por item da lista.htmlFor, aria-labelledby), não para props key.item.id) ou identificadores estáveis para listas.const id = useId();
const nameId = `${id}-name`;
const emailId = `${id}-email`;
const helpId = `${id}-help`;useId.useId gera IDs como :r1: com dois pontos para evitar colisões com IDs definidos pelo usuário.id HTML, mas devem ser escapados em seletores CSS: #\:r1\:.[id="valor"] em vez de seletores de ID em CSS.:r1:, :r2:, etc.).identifierPrefix em createRoot ou hydrateRoot para nomear os IDs.const root = createRoot(container, { identifierPrefix: "app1-" });
// IDs: ":app1-r1:", ":app1-r2:", etc.useId deve ser chamado no nível superior do seu componente.// useId sempre retorna string -- nenhum genérico é necessário
const id: string = useId();string.interface InputProps {
id?: string;
label: string;
}
function Input({ id: propId, label }: InputProps) {
const generatedId = useId();
const inputId = propId ?? generatedId;
return (
<>
<label htmlFor={inputId}>{label}</label>
<input id={inputId} />
</>
);
}:r1:) é um detalhe de implementação e pode mudar entre as versões do React.useId() no mesmo componente retorna um ID único.useIduseIdRevisado por Chris St. John·Última atualização: 16 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥