useId() is one of the latest hooks added to React 18. Its primary use case is to generate unique IDs for HTML form elements and ensure that the IDs are always unique in the context of the React application.
What is the useId() Hook?
The useId() hook provides a way to generate unique IDs that persist between re-renders. It ensures that generated IDs are unique across the entire React app, and until the component that uses the ID is removed from the DOM. Once the component is re-insterted, the generated ID will be different.
The main purpose of the useId() hook is to generate unique IDs for HTML form elements. It simplifies the process of generating unique IDs when creating form inputs and labels in React.
How to Use useId() Hook?
Using the useId() hook is very straight-forward. The hook can be called simply by writing const id = useId(); in your component code. The useId() hook doesn’t take any parameters.
See below example, where useId hook is used to generate unique ID in the Form component and it is utilized to connect label and input tags.
function Form() {
const id = useId();
return (
<>
<label htmlFor={id}>First Name</label>
<input id={id} type="text" placeholder={`Generated id --> ${id}`} />
</>
)
}
The id will be unique across the React app and it will persist till component persists in the DOM.
What if we re-use this Form component for multiple times ? Will both components have same id ?
No. Each instance of the component will have different and unique id across the React app.
What if we want multiple unique id in the same component ?
We can create as many unique id as we want but wait you may not need it.
Let’s extend the same Form component and add last-name and email inputs.
function Form() {
const idForFirstName = useId();
const idForLastName = useId();
const idForEmail = useId();
return (
<>
<label htmlFor={idForFirstName}>First Name</label>
<input id={idForFirstName} type="text" placeholder={`Generated id --> ${idForFirstName}`} />
<label htmlFor={idForLastName}>Last Name</label>
<input id={idForLastName} type="text" placeholder={`Generated id --> ${idForLastName}`} />
<label htmlFor={idForEmail}>Email</label>
<input id={idForEmail} type="email" placeholder={`Generated id --> ${idForEmail}`} />
</>
)
}
You can see in above example that we are creating 3 unique ids with useId() hook but this is an anti-pattern. Suppose we require not 3 but 10 or 15 ids. With this manner we will end up creating 10 to 15 unique ids by calling hooks for 10 to 15 times. Seems odd right ?
Usually in such cases, we can prefix single generated id and reuse it at multiple places, see below example.
function Form() {
const id = useId();
return (
<>
<label htmlFor={`${id}--firstName`}>First Name</label>
<input id={`${id}--firstName`} type="text" placeholder={`Generated id --> ${id}`} />
<label htmlFor={`${id}--lastName`}>Last Name</label>
<input id={`${id}--lastName`} type="text" placeholder={`Generated id --> ${id}`} />
<label htmlFor={`${id}--email`}>Email</label>
<input id={`${id}--email`} type="email" placeholder={`Generated id --> ${id}`} />
</>
)
}
We know that we have a unique id so by prefixing or suffixing it we can utilize it several times in the single component.
As we know that unique id generated by useId hook is unique across React app.
What if we are rendering multiple React app in the single page ?
To make sure that the id generated by useId hook is unique across the page we can utilize identifierPrefix option, see below example.
const sectionA = createRoot(document.getElementById('root1'), {
identifierPrefix: 'app-sectionA-'
});
sectionA.render(<App />);
const sectionB = createRoot(document.getElementById('root2'), {
identifierPrefix: 'app-sectionB-'
});
sectionB.render(<App />);
Now generated ids will look like this;
:app-sectionA-r0:
&
:app-sectionB-r0:
Note: Don’t use useId hook to generate keys. It’s main purpose is to generate unique ids for Form element’s id attribute.
By utilizing the useId() hook, it’s easy to generate unique IDs for HTML form elements in React. It simplifies the process and ensures that the IDs are always unique across the entire React app, ensuring a more streamlined and error-free development process.