← Назад к вопросам

Для чего нужен useId?

1.6 Junior🔥 91 комментариев
#Soft Skills и рабочие процессы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Хук 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 приложений