Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Хук useId в React
useId - это встроенный хук React (появился в версии 18), предназначенный для генерации уникальных идентификаторов. Это решает важную задачу в разработке фронтенда, особенно при использовании SSR (Server-Side Rendering) и поддержке доступности (a11y).
Основное назначение
Hook useId генерирует стабильный уникальный идентификатор для элемента, который:
- Синхронизируется между клиентом и сервером при SSR
- Не вызывает hydration mismatch
- Остаётся неизменным между рендерами
- Уникален для каждого экземпляра компонента
Синтаксис и базовое использование
import { useId } from 'react';
function MyComponent() {
const id = useId();
return (
<div>
<label htmlFor={id}>Введите имя:</label>
<input id={id} type="text" />
</div>
);
}
Основные варианты применения
1. Связь меток с инпутами (accessibility)
Это самый частый случай использования - связать элемент label с input через атрибут htmlFor:
interface InputProps {
label: string;
type?: string;
placeholder?: string;
}
export function Input({ label, type = 'text', placeholder }: InputProps) {
const id = useId();
return (
<div className="form-group">
<label htmlFor={id} className="label">
{label}
</label>
<input
id={id}
type={type}
placeholder={placeholder}
className="input"
/>
</div>
);
}
2. ARIA атрибуты для скрин-ридеров
function Dialog({ title, content }) {
const titleId = useId();
const descId = useId();
return (
<div
role="dialog"
aria-labelledby={titleId}
aria-describedby={descId}
>
<h2 id={titleId}>{title}</h2>
<p id={descId}>{content}</p>
</div>
);
}
3. SVG элементы с gradients и masks
function AnimatedIcon() {
const gradientId = useId();
return (
<svg viewBox="0 0 100 100">
<defs>
<linearGradient id={gradientId}>
<stop offset="0%" stopColor="#ff0000" />
<stop offset="100%" stopColor="#0000ff" />
</linearGradient>
</defs>
<circle cx="50" cy="50" r="40" fill={`url(#${gradientId})`} />
</svg>
);
}
Важное свойство: SSR совместимость
Основное преимущество useId - он решает проблему hydration mismatch при SSR:
// БЕЗ useId (неправильно для SSR)
function BadComponent() {
const id = Math.random().toString(); // Разные на сервере и клиенте!
return <label htmlFor={id}>Label</label>;
}
// С useId (правильно для SSR)
function GoodComponent() {
const id = useId(); // Одинаковый на сервере и клиенте
return <label htmlFor={id}>Label</label>;
}
Сравнение с альтернативами
Альтернатива 1: Просто передать id как prop
// Когда компонент используется несколько раз - проблема
<Input id="name" />
<Input id="name" /> // Конфликт - два элемента с одинаковым id!
Альтернатива 2: uuid() или Math.random()
// Работает на клиенте, но ломается при SSR
const id = Math.random().toString();
useId - правильный выбор потому что:
- Уникален для каждого экземпляра
- Гарантирует стабильность при SSR
- Не требует внешних зависимостей
Практический пример: переиспользуемый компонент Checkbox
interface CheckboxProps {
label: string;
checked?: boolean;
onChange?: (checked: boolean) => void;
}
export function Checkbox({ label, checked = false, onChange }: CheckboxProps) {
const id = useId();
return (
<div className="checkbox-wrapper">
<input
id={id}
type="checkbox"
checked={checked}
onChange={(e) => onChange?.(e.target.checked)}
className="checkbox-input"
/>
<label htmlFor={id} className="checkbox-label">
{label}
</label>
</div>
);
}
// Использование
function Form() {
return (
<>
<Checkbox label="Согласен с условиями" />
<Checkbox label="Подписаться на рассылку" />
<Checkbox label="Получать уведомления" />
</>
);
}
Важные ограничения
1. Нельзя использовать в условиях
// ПЛОХО - нарушение правила хуков
if (someCondition) {
const id = useId();
}
// ХОРОШО - всегда вызывается
const id = useId();
if (someCondition) {
// используем id
}
2. Не для key в списках
// НЕПРАВИЛЬНО
{items.map(() => {
const id = useId();
return <div key={id}>...</div>; // Плохая идея!
})}
// ПРАВИЛЬНО - используй стабильный идентификатор из данных
{items.map(item => (
<div key={item.id}>...</div>
))}
3. Уникален внутри одного компонента
function Component() {
const id1 = useId();
const id2 = useId();
// id1 !== id2
}
Версионность
- Доступен в React 18+
- Для более старых версий можно использовать: uuid, nanoid или самостоятельную реализацию
- В Next.js рекомендуется использовать именно useId для SSR приложений