The useId()
hook is a new addition to React 18. Its main purpose is to create unique IDs for HTML form elements. It makes sure that these IDs are always unique within the React application.
If we use the Form component multiple times, each instance will have a different and unique ID across the React app. They won’t share the same ID.
Important: Do not utilize the useId hook for generating keys. Its primary function is to produce unique IDs specifically for the id attribute of elements.
Contents
What is useId
Hook?
React 18 brings with it an array of new features and improvements, one of which is the introduction of the useId
hook. This innovative hook is designed to generate unique IDs on both the client and server, while also addressing the issue of hydration mismatches. In this article, we will delve into the significance of the useId
hook, its applications, and why it’s a game-changer for React developers.
useId
hook is a React Hook designed to create distinct IDs that can be assigned to accessibility attributes.
How to use useId
Hook?
Integrate the useId
Hook at the component’s top level to generate a distinct ID.
The useId
Hook does not accept any parameters. But when invoked useId, will provide a unique ID string specific to that useId
call within the given component.
Since useId
is a Hook, it should only be invoked at the highest level of your component or within your custom Hooks. Avoid using it within loops or conditional statements. If such a scenario arises, consider creating a new component and transferring the state accordingly.
It’s important to note that useId
IS NOT intended for generating keys in a list. Instead, keys should be generated based on your data.
import { useId } from 'react'; function InputField() { const hintId = useId(); // ... return ( <> <input type="password" aria-describedby=hintId} /> <p id={hintId}> </> )
Example to understand the pros of this concept.
HTML accessibility attributes, such as aria-describedby, allow you to establish relationships between two tags. For instance, you can indicate that an element, like an input field, is described by another element, like a paragraph.
For example in HTML you would have something like this:
<label> Create a Secure Password: <input type="password" aria-describedby="password-security-info" /> </label> <p id="password-security-info"> For optimal security, your password should consist of a combination of letters, numbers, and special characters and be at least 12 characters long. </p>
However, hardcoding IDs in this manner isn’t considered a best practice in React. A component might get rendered multiple times on a page, but IDs must remain unique. Instead of manually assigning an ID, you can generate a unique one using the useId
Hook.
import { useId } from 'react'; function PasswordInputField() { const passwordId = useId(); return ( <> <label> Password: <input type="password" aria-describedby={passwordId} /> </label> <p id={passwordId}> For optimal security, your password should consist of a combination of letters, numbers, and special characters and be at least 12 characters long. </p> </> ); }
By doing so, even if a component like `PasswordInputField` appears multiple times on the screen, the generated IDs won’t conflict with each other.
Generating IDs for Multiple Related Elements
When you need to assign IDs to several related elements, you can use the useId
Hook to generate a shared prefix for them. This approach saves you from having to call useId for every individual element requiring a unique ID.
import { useUniqueId } from 'react'; export default function UserForm() { const uniqueId = useUniqueId(); return ( <form> <label htmlFor={`${uniqueId}"-firstName"`}>First Name:</label> <input id={`${uniqueId}"-firstName"`} type="text" /> <hr /> <label htmlFor={`${uniqueId}"-lastName"`}>Last Name:</label> <input id={`${uniqueId}"-lastName"`} type="text" /> </form> ); }
If you’re rendering multiple independent React applications on a single page, you can pass identifierPrefix
as an option to your createRoot
or hydrateRoot
calls. This ensures that the IDs generated by these different apps never clash because every identifier created using the useId
Hook will begin with the unique prefix you’ve specified.”
import { createCustomRoot } from 'react-dom/client'; import MyApp from './MyApp.js'; import './custom-styles.css'; const firstAppRoot = createCustomRoot(document.getElementById('first-app-root'), { customPrefix: 'app-one-' }); firstAppRoot.render(<MyApp />); const secondAppRoot = createCustomRoot(document.getElementById('second-app-root'), { customPrefix: 'app-two-' }); secondAppRoot.render(<MyApp />);
NOTE:
useId
produces a string that contains a colon (:), ensuring its uniqueness. However, it’s important to note that this format isn’t compatible with CSS selectors or APIs such asquerySelectorAll
.
To avoid conflicts in applications with multiple roots,
useId
provides support for anidentifierPrefix
For configuration details, refer to the options available for hydrateRoot and ReactDOMServer.
Conclusion
In conclusion, the useId hook in React is a valuable tool for generating unique IDs for HTML elements, particularly in scenarios that require accessibility compliance.
It addresses the issue of hydration mismatches and provides flexibility with identifier prefixes for multi-root applications. By understanding and utilizing the useId hook, developers can enhance the reliability and accessibility of their web applications, ensuring a smoother and more consistent user experience.
0 Comments