useId
Generates stable unique IDs for accessibility attributes and form element associations.
Basic Usage
Live Editor
function Demo() { const id = useId(); return ( <div> <div style={{ padding: '20px', backgroundColor: 'var(--ifm-color-emphasis-100)', borderRadius: '8px', marginBottom: '12px', }} > <div style={{ marginBottom: '8px' }}> Generated ID: <code style={{ color: 'var(--ifm-color-primary)' }}>{id}</code> </div> <div style={{ fontSize: '14px', color: 'var(--ifm-color-emphasis-700)' }}> Stable across renders </div> </div> </div> ); }
Result
Loading...
Form Label Association
Use ID to associate label and input:
Live Editor
function Demo() { const id = useId(); return ( <div> <div style={{ marginBottom: '12px' }}> <label htmlFor={id} style={{ display: 'block', marginBottom: '8px', fontWeight: 'bold', }} > Username </label> <Input id={id} placeholder="Enter username" /> </div> <div style={{ padding: '12px', backgroundColor: 'var(--ifm-color-emphasis-100)', borderRadius: '6px', fontSize: '14px', }} > <strong>Associated ID:</strong> <code>{id}</code> </div> </div> ); }
Result
Loading...
ARIA Attributes
Use IDs to connect ARIA attributes:
Live Editor
function Demo() { const buttonId = useId(); const contentId = useId(); const [expanded, setExpanded] = useState(false); return ( <div> <Button id={buttonId} aria-expanded={expanded} aria-controls={contentId} onClick={() => setExpanded(!expanded)} > {expanded ? 'Collapse' : 'Expand'} Content </Button> {expanded && ( <div id={contentId} role="region" aria-labelledby={buttonId} style={{ marginTop: '12px', padding: '16px', backgroundColor: 'var(--ifm-background-surface-color)', border: '1px solid var(--ifm-color-emphasis-300)', borderRadius: '8px', }} > This is the expandable content region, associated with the button via ARIA attributes. </div> )} <div style={{ marginTop: '12px', padding: '12px', backgroundColor: 'var(--ifm-color-emphasis-100)', borderRadius: '6px', fontSize: '14px', }} > <div>Button ID: <code>{buttonId}</code></div> <div>Content ID: <code>{contentId}</code></div> </div> </div> ); }
Result
Loading...
Multiple Inputs
Generate unique IDs for multiple form fields:
Live Editor
function Demo() { const nameId = useId(); const emailId = useId(); const phoneId = useId(); return ( <div> <div style={{ marginBottom: '12px' }}> <label htmlFor={nameId} style={{ display: 'block', marginBottom: '4px' }}> Name </label> <Input id={nameId} placeholder="Enter name" /> </div> <div style={{ marginBottom: '12px' }}> <label htmlFor={emailId} style={{ display: 'block', marginBottom: '4px' }}> Email </label> <Input id={emailId} type="email" placeholder="Enter email" /> </div> <div style={{ marginBottom: '12px' }}> <label htmlFor={phoneId} style={{ display: 'block', marginBottom: '4px' }}> Phone </label> <Input id={phoneId} type="tel" placeholder="Enter phone" /> </div> </div> ); }
Result
Loading...
API
Parameters
function useId(staticId?: string): string
| Parameter | Description | Type | Default |
|---|---|---|---|
| staticId | Static ID (optional) | string | undefined |
Return Value
Returns a stable unique ID string.
string
Features
- Stability: Remains constant throughout component lifecycle
- Uniqueness: Guaranteed unique across the entire application
- SSR Compatible: IDs generated on server and client are consistent
- Overridable: Can provide custom ID via parameter
Notes
- If
staticIdis provided, that ID will be used directly - Do not use generated IDs as React keys
- IDs are not reused after component unmount
- Suitable for scenarios requiring element associations
Usage Scenarios
- Form Labels: Associate label and input elements
- ARIA Attributes:
aria-labelledby,aria-describedby, etc. - Accessibility: Enhance screen reader experience
- Element Association: Any scenario requiring unique ID for element association
- Error Messages: Associate form fields with error messages
Difference from React 18
If you're using React 18+, you can use the built-in useId Hook directly. The useId from @kubed/hooks provides the same API as React 18 while being compatible with React 17 and earlier versions.
// React 18+ built-in
import { useId } from 'react';
// @kubed/hooks version (compatible with React 17)
import { useId } from '@kubed/hooks';