DOM и React Senior Компоненты на практике обновлено

Выпадающий список

Условие

Свой select. Требования: · кнопка <button class="trigger"> показывает выбранное значение или «Выберите»; · список - <ul class="menu"> с <li class="option" data-value={value}>; · список открывается и закрывается кликом по кнопке; · выбор пункта закрывает список и вызывает onChange(value); · клик вне компонента закрывает список; · Escape закрывает; · у кнопки aria-expanded, у выбранного пункта aria-selected.

Что проверяют тесты

  • закрыт по умолчанию

  • открывается и закрывается кнопкой

  • выбор закрывает и сообщает наружу

  • клик снаружи закрывает

  • клик внутри не закрывает

  • Escape закрывает

  • слушатели снимаются при закрытии

Как подойти

Три способа закрытия и одна общая ловушка: клик по самой кнопке дойдёт и до document-слушателя, и до onClick кнопки - получится открыть-и-сразу-закрыть. Спасает проверка contains: кнопка внутри root, поэтому внешний обработчик её игнорирует. mousedown вместо click - потому что к моменту click кликнутый пункт уже может быть размонтирован, и contains вернёт false. Что назвать вслух: навигация стрелками и Home/End, набор первых букв, role=listbox с aria-activedescendant, позиционирование в портале.

Подсказки: 3
  1. Определение «клик снаружи» - это !root.contains(e.target).
  2. Слушатель вешается только пока список открыт - и снимается в очистке эффекта.
  3. mousedown, а не click: пункт может быть удалён из дерева до всплытия click.

Решите в тренажёре

Редактор с автотестами прямо в браузере. Можно решить спокойно, вслух или под таймером, как на собесе.