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

Автодополнение

Условие

Поле поиска с выпадающим списком. Требования: · <input class="q">; список - <ul class="list"> с <li class="opt">; · подсказки запрашиваются функцией search(query), она возвращает промис; · запрос уходит с задержкой 50 мс после окончания ввода; · пустой запрос список не показывает и запрос не шлёт; · ответы на устаревшие запросы игнорируются; · ↓ и ↑ двигают выделение (класс "active"), Enter выбирает, Escape закрывает; · выбор кладёт значение в поле и закрывает список.

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

  • пустой запрос ничего не шлёт

  • показывает подсказки

  • схлопывает быстрый ввод

  • устаревший ответ не перетирает

  • стрелки и Enter выбирают

  • стрелки ходят по кругу

  • Escape закрывает

  • клик по подсказке выбирает

Как подойти

Самая частая задача на фронтовом лайвкодинге, и она проверяет сразу четыре вещи: debounce, гонку ответов, клавиатуру и сброс производных состояний. Порядок сдачи: сначала поле и список, потом задержка, потом гонка, потом клавиатура - так на любом таймере остаётся работающая версия. Счётчик держим в ref, потому что его изменение не должно вызывать рендер. Что назвать вслух как следующий шаг: закрытие по клику снаружи, aria-combobox с aria-activedescendant, отмена запроса через AbortController, подсветка совпадения.

Подсказки: 5
  1. Состояний четыре: запрос, список, открыт ли список, индекс выделения.
  2. Задержка живёт в эффекте: очистка эффекта отменяет прошлый таймер.
  3. От гонки спасает счётчик запросов в ref, а не флаг - запросов может быть много.
  4. Выделения может не быть вовсе (-1) - у стрелок вверх и вниз это разные стартовые случаи.
  5. При новом списке выделение надо сбрасывать, иначе индекс укажет в пустоту.

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

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