


У двух экземпляров поля формы не должно быть одного жёстко заданного id. Хук useId помогает создать идентификатор для связей доступности внутри компонента. В практикуме Mentoring.digital соберём поле с подписью и пояснением.
import { useId } from "react";
function EmailField({ label }) {
const baseId = useId();
const hintId = `${baseId}-hint`;
return (
<div>
<label htmlFor={baseId}>{label}</label>
<input id={baseId} type="email"
aria-describedby={hintId} />
<p id={hintId}>Укажите адрес для ответа.</p>
</div>
);
}
HtmlFor у label указывает на id поля. Aria-describedby у input указывает на отдельный элемент с подсказкой. Для нескольких связанных элементов можно получить один базовый ID и добавить понятные суффиксы.
Вызовите компонент дважды, например для основного и дополнительного адреса. У каждого экземпляра будут свои связи. Не нужно передавать один и тот же постоянный идентификатор всем полям.
Нажатие на подпись должно переводить фокус в соответствующее поле. Проверьте отдельно обе подписи: ошибка с повторяющимся id часто проявляется тем, что фокус всегда попадает в первый input.
Затем пройдите форму клавишей Tab. Для проверки доступного имени и описания используйте дерево доступности браузера или подходящий инструмент чтения с экрана. Наличие атрибута само по себе не доказывает, что весь пользовательский сценарий формы доступен.
Пример отвечает только за идентификаторы. Он не добавляет сохранение данных, обработку отправки или проверку бизнес-правил. Эти части формы нужно проектировать и проверять отдельно.
UseId вызывается на верхнем уровне компонента или собственного хука. Его нельзя помещать в условие или цикл. Если список содержит много полей, вынесите отдельное поле в компонент и вызывайте хук внутри него.
Не используйте useId для key элементов списка. Key должен происходить из данных и помогать React сопоставлять элементы при изменении списка. Идентификатор связи label и input решает другую задачу.
При серверном рендеринге дерево компонентов на сервере и клиенте должно согласовываться. Если на странице несколько независимых корней React, предусмотрите разные identifierPrefix, а для гидратации одного корня сохраняйте одинаковый префикс с обеих сторон.
Задание: добавьте вторую подсказку об ошибке с суффиксом error и продумайте, когда её ID попадает в aria-describedby. Затем проверьте форму с двумя экземплярами поля. Такой компонент можно разобрать на практическом курсе React и обсудить с ментором по React.