MENU
useId
useId() takes no parameters and returns a single ID string that's unique to that particular call in that particular component instance, and stays the same across re-renders. It exists for wiring up accessibility attributes that need to reference each other – connecting an <input> to its hint text through aria-describedby, say, or a <label> to its field through htmlFor/id – especially inside a reusable component that might get rendered many times on the same page, where a hardcoded id string would collide.
useId() should not be used to generate keys for a list – keys should always come from your data – and not for cache keys passed to use() either. With server rendering it also requires the server and client to render an identical component tree, since the generated ids are derived from each component's position within it; mismatched trees produce mismatched ids. (It currently can't be called inside an async Server Component at all, though that's less likely to come up in the client-rendered demos on this page.)
RESETRUNFULL
<!DOCTYPE html><html><head>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head><body>
<div></div>
<script type="text/babel">
function PasswordField() {
const passwordHintId = React.useId();
return (
<div>
<label>Password: <input type="password" aria-describedby={passwordHintId} /></label>
<p id={passwordHintId}>id = {passwordHintId}</p>
</div>
);}
function App() {
return (
<React.Fragment>
<PasswordField />
<PasswordField />
</React.Fragment>
);}
const root = ReactDOM.createRoot(document.querySelector("div"));
root.render(<App/>);
</script>
</body></html>A single call can also seed several related ids at once, by appending different suffixes to it:
RESETRUNFULL
<!DOCTYPE html><html><head>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head><body>
<div></div>
<script type="text/babel">
function NameForm() {
const id = React.useId();
return (
<form>
<label htmlFor={id + '-firstName'}>First Name: </label>
<input id={id + '-firstName'} type="text" />
<br/>
<label htmlFor={id + '-lastName'}>Last Name: </label>
<input id={id + '-lastName'} type="text" />
</form>
);}
const root = ReactDOM.createRoot(document.querySelector("div"));
root.render(<NameForm/>);
</script>
</body></html>