Como resolver o erro non-unique ID em componentes compartilhados usando React
Se você já deu uma olhada na documentação de design para desenvolvedores do The Chromium Projects, provavelmente encontrou a seguinte recomendação na seção Create Amazing Password Forms:
Os navegadores foram projetados levando em consideração a especificação HTML, e ir contra ela pode causar comportamentos inesperados na sua página. Isso significa:
Os atributos
iddos elementos devem ser únicos: dois elementos não podem ter o mesmoid.
Mas, na prática, é extremamente comum termos componentes compartilhados reutilizando o mesmo ID em diferentes partes da aplicação — principalmente quando existem múltiplas instâncias do mesmo componente sendo renderizadas na mesma página.
Um dos exemplos mais clássicos disso é um componente de LoginForm:
// <LoginForm /> component:
function LoginForm() => (
<form>
...
<label htmlFor="username">
Username
</label>
<input
id="username"
type="text"
name="username"
placeholder="Username"
/>
...
</form>
);
...// Homepage
<>
<header>
<LoginForm /> {/* primeira instância */}
</header>
<main>
...
</main>
<footer>
<LoginForm /> {/* segunda instância */}
</footer>
</>Perceba que as duas instâncias do componente LoginForm acabam gerando o mesmo ID (username), o que não é permitido pela especificação HTML.
E eu sei que muita gente pode pensar em resolver isso passando uma prop id diferente para cada instância do componente. Funciona? Até funciona. Mas não é a melhor abordagem.
É aí que entra o hook React.useId()
O React oferece o hook useId, que gera um ID único para cada instância do componente.
import { useId } from 'react';
function LoginForm() {
const id = useId();
const usernameId = `${id}-username`;
return (
<form>
<label htmlFor={usernameId}>
Username
</label>
<input
id={usernameId}
type="text"
name="username"
placeholder="Username"
/>
</form>
);
}Se você der um console.log no valor de id, verá algo parecido com isso:

E o melhor: esse valor permanece o mesmo entre re-renderizações do componente, o que torna essa solução muito mais confiável do que depender de props manuais ou alternativas como Math.random().
Até a próxima! 👋🏾