useId } from 'react';
    
    function PasswordField() {
      const passwordHintId = useId();
      return (
        <>
          <label>
            Password:
            <input
              type="password"
              aria-describedby={passwordHintId}
            />
          </label>
          <p id={passwordHintId}>
            The password should contain at least 18 characters
          </p>
        </>
      );
    }
    
    export default function App() {
      return (
        <>
          <h2>Choose password</h2>
          <PasswordField />
          <h2>Confirm password</h2>
          <PasswordField />
        </>
      );
    }
    
    

Show more

[ Watch this video ](https://www.youtube.com/watch?v=0dNzNcuEuOo) to see the
difference in the user experience with assistive technologies.

###  Pitfall

With [ server rendering ](/reference/react-dom/server) , **` useId ` requires
an identical component tree on the server and the client ** . If the trees you
render on the server and the client don’t match exactly, the generated IDs
won’t match.

#####  Deep Dive

####  Why is useId better than an incrementing counter?

Show Details

You might be wondering why ` useId ` is better than incrementing a global
variable like ` nextId++ ` .

The primary benefit of ` useId ` is that React ensures that it works with [
server rendering. ](/reference/react-dom/server) During server rendering, your
components generate HTML output. Later, on the client, [ hydration
](/reference/react-dom/client/hydrateRoot) attaches your event handlers to the
generated HTML. For hydration to work, the client output must match the server
HTML.

This is very difficult to guarantee with an incrementing counter because the
order in which the Client Components are hydrated may not match the order in
which the server HTML was emitted. By calling ` useId ` , you ensure that
hydration will work, and the output will match between the server and the
client.

Inside React, ` useId ` is generated from the “parent path” of the calling
component. This is why, if the client and the server tree are the same, the
“parent path” will match up regardless of rendering order.

* * *

###  Generating IDs for several related elements

If you need to give IDs to multiple related elements, you can call ` useId `
to generate a shared prefix for them:

App.js

App.js

Reset  [ Fork
](https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-
react-app "Open in CodeSandbox")

    
    
    import { useId } from 'react';
    
    export default function Form() {
      const id = useId();
      return (
        <form>
          <label htmlFor={id + '-firstName'}>First Name:</label>
          <input id={id + '-firstName'} type="text" />
          <hr />
          <label htmlFor={id + '-lastName'}>Last Name:</label>
          <input id={id + '-lastName'} type="text" />
        </form>
      );
    }
    
    

This lets you avoid calling ` useId ` for every single element that needs a
unique ID.

* * *

###  Specifying a shared prefix for all generated IDs

If you render multiple independent React applications on a single page, pass `
identifierPrefix ` as an option to your [ ` createRoot ` ](/reference/react-
dom/client/createRoot#parameters) or [ ` hydrateRoot ` ](/reference/react-
dom/client/hydrateRoot) calls. This ensures that the IDs generated by the two
different apps never clash because every identifier generated with ` useId `
will start with the distinct prefix you’ve specified.

index.js  index.html  App.js

index.js

Reset  [ Fork
](https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-
react-app "Open in CodeSandbox")

    
    
    import { createRoot } from 'react-dom/client';
    import App from './App.js';
    import './styles.css';
    
    const root1 = createRoot(document.getElementById('root1'), {
      identifierPrefix: 'my-first-app-'
    });
    root1.render(<App />);
    
    const root2 = createRoot(document.