Корректно ли генерировать уникальный id для ключей в React при отсутствии id в данных с бэка и вызовет ли это проблемы с оптимизацией рендера
Что проверяют
Понимаете ли вы, что делает key при согласовании дерева, и различаете ли «сгенерировать id один раз» и «генерировать его на каждом рендере». Следом обычно просят объяснить, почему индекс массива в роли ключа ломает состояние полей ввода.
Как отвечать
Сама идея сгенерировать id на клиенте корректна. Всё решает момент генерации.
- ключ в
mapчерезMath.random()илиcrypto.randomUUID(): на каждом рендере ключи новые, React считает все элементы новыми, размонтирует старые и монтирует заново. Теряется локальное состояние, фокус и позиция курсора в инпутах, DOM пересоздаётся, эффекты отрабатывают повторно,React.memoбесполезен; - id при получении данных: присвоить
crypto.randomUUID()каждому элементу один раз, когда ответ пришёл и кладётся в состояние или в кэш запросов. Ключ стабилен всё время жизни элемента, и это нормальное решение. Учтите, чтоcrypto.randomUUID()доступен только в защищённом контексте, то есть по HTTPS или на localhost; - ключ из содержимого: если в данных есть поле или сочетание полей, уникальное среди соседей, берите его. Уникальность нужна только внутри одного списка, а не глобально;
- индекс: допустим, если список статичен, не сортируется, не фильтруется и в середину ничего не вставляют.
Уточните механику: key не отменяет перерисовку. Если родитель перерендерился, дочерние компоненты тоже вызовутся, если они не обёрнуты в memo. Ключ решает другое: обновить существующий экземпляр или выбросить его и создать новый. Размонтирование с монтированием заметно дороже обновления.
Лучший вариант в долгую: попросить бэкенд отдавать стабильный идентификатор, особенно если элементы потом редактируют и отправляют обратно.
Где спотыкаются
Предлагают useId. Этот хук даёт id для атрибутов доступности, его нельзя вызывать в цикле, и для ключей списка он не предназначен.
Советуют склеить поле с индексом. Индекс в составе ключа сдвигается при вставке и удалении, так что проблема индекса возвращается.
Ждут, что React предупредит об ошибке. Он ругается только на отсутствующие и повторяющиеся ключи, а случайные ключи молча превращают каждый рендер в пересоздание списка.