The useId Hook
Video Summary
- A core idea with React is that components are reusable. We should be able to render multiple instances of just about any component without anything blowing up.
- However, certain aspects of the web platform aren't built with reusability in mind. For example,
id
attributes need to be globally unique! How can we create reusable components without accidentally violating this rule? - Well, we could add a new prop to the component, like
id
. That way, the developer can specify a unique value for each instance. - This works, but it depends on the developer remembering to supply a value, and making sure that it's globally unique. This is easier said than done!
- Fortunately, the React team has created a new tool to help us out: the
useId
hook. - Inside our component, we can type:
function LoginForm() { const id = React.useId();}
- Each instance of this component will receive a different value. For example, if we render 2 instances, we'll notice that the
id
variable is equal to:r0:
in the first one and:r1:
in the second. - React hooks “hook into” the component instance. And so this ID lives on the instance, and can be plucked out during render.
- This means that the value persists across renders.
id
will always be equal to:r0:
, in that first instance, on every single render.
Here's the playground from the video:
Code Playground
import React from 'react';
function LoginForm() {
const [username, setUsername] = React.useState('');
const [password, setPassword] = React.useState('');
// Pluck this instance's unique ID from React
const id = React.useId();
// Create element IDs using this unique ID
const usernameId = `${id}-username`;
const passwordId = `${id}-password`;
return (
<form className="login-form">
<div>
{/* Apply these IDs to the label and input */}
<label htmlFor={usernameId}>
Username:
</label>
<input
type="text"
id={usernameId}
value={username}
onChange={event => {
setUsername(event.target.value);
}}
/>
</div>
<div>
<label htmlFor={passwordId}>
Password:
</label>
<input
type="password"
id={passwordId}
value={password}
onChange={event => {
setPassword(event.target.value);
}}
/>
</div>
<button>
Submit
</button>
</form>
);
}
export default LoginForm;
Practice — Toggle component
In this sandbox, you'll find a Toggle
component that has been almost fully implemented.
Finish it up by adding a unique ID to the button, and connecting it to the label. You should be able to trigger the toggle by clicking the "Dark Mode" text.
Code Playground
import React from 'react';
import styles from './Toggle.module.css';
function Toggle({
label,
checked,
handleToggle,
backdropColor = 'white',
size = 16,
}) {
const padding = size * 0.1;
const width = size * 2 + padding * 2;
const wrapperStyle = {
width,
padding,
'--radius': size * 0.25 + 'px',
'--backdrop-color': backdropColor,
};
const ballStyle = {
width: size,
height: size,
transform: checked ? `translateX(100%)` : `translateX(0%)`,
};
return (
<div className={styles.wrapper}>
<label>
{label}
</label>
<button
className={styles.toggle}
type="button"
aria-pressed={checked}
style={wrapperStyle}
onClick={() => {
handleToggle(!checked)
}}
>
<span className={styles.ball} style={ballStyle} />
</button>
</div>
);
};
export default Toggle;