Видеоуроки, интерактивный редактор и сохранение прогресса — бесплатно, сразу после входа.
ВойтиСоздать аккаунт — бесплатноЗакончили урок?
Войдите, чтобы отмечать прогресс
В этом решении мы создаём поисковую систему с автоматическими подсказками и оптимизацией через debounce.
Мы используем пять состояний для управления поиском. searchQuery хранит текст из поля ввода. suggestions - это короткий список для выпадающего меню (максимум 5 элементов). showSuggestions контролирует видимость выпадающего списка. filteredCountries - все найденные результаты для основного списка. isSearching показывает индикатор загрузки во время поиска.
Если поле пустое, мы очищаем все результаты и выходим из эффекта. Ранний return предотвращает создание таймера и выполнение поиска. Это экономит ресурсы - нет смысла искать, когда запрос пустой.
Мы сразу устанавливаем isSearching в true для показа индикатора. Затем создаём таймер, который выполнится через 300 миллисекунд. Если за это время searchQuery изменится, cleanup функция clearTimeout отменит старый таймер, и создастся новый. Поиск выполнится только когда пользователь перестанет печатать на 300мс.
Мы сохраняем запрос в нижнем регистре в переменную для многократного использования. Метод filter проверяет каждую страну - совпадение должно быть либо в названии, либо в столице. Оператор || (ИЛИ) означает, что достаточно одного совпадения. Метод includes() проверяет, содержится ли подстрока в строке.
Для автокомплита берём только первые 5 результатов с помощью slice(0, 5). Это делает выпадающий список компактным. Но полный список результатов сохраняем в filteredCountries - он используется для отображения всех найденных стран ниже.
При каждом изменении текста мы обновляем запрос и показываем выпадающий список. Установка showSuggestions в true гарантирует, что подсказки появятся, даже если пользователь ранее закрыл их.
Когда пользователь кликает на подсказку, мы заполняем поле выбранным названием и скрываем выпадающий список. Обновление searchQuery автоматически запустит useEffect, который отфильтрует результаты для выбранной страны.
Функция находит первое вхождение запроса в тексте с помощью indexOf(). Если совпадение найдено, мы разбиваем текст на три части: до совпадения, само совпадение (обёрнутое в <span> для стилизации) и после совпадения. Метод substring(start, end) извлекает часть строки. Если совпадения нет (index === -1), возвращаем оригинальный текст.
Событие onFocus срабатывает, когда пользователь кликает в поле ввода. Мы показываем подсказки, если они были скрыты. Это улучшает UX - пользователь может снова увидеть подсказки, просто вернувшись в поле, без повторного ввода.
Пока идёт поиск, показываем песочные часы. Когда поиск завершён, показываем лупу. Это визуальная обратная связь - пользователь видит, что система обрабатывает его запрос.
Выпадающий список показывается только когда все условия истинны: флаг showSuggestions включён, есть подсказки, и запрос не пустой. Оператор && работает как цепочка проверок - если хотя бы одно условие ложно, список не рендерится.
Мы применяем подсветку и к названию страны, и к столице. Разделитель {' • '} - это текстовая точка с пробелами, обёрнутая в фигурные скобки для корректной обработки React. Пользователь видит, какая часть текста совпала с его запросом.
Вложенный тернарный оператор выбирает правильное склонение. Если результат один, используем единственное число "страна". Если от 2 до 4, используем "страны". Для всех остальных случаев (0, 5 и больше) - "стран". Это делает текст грамматически правильным на русском языке.
Вложенный тернарный оператор обрабатывает три сценария. Первый - запрос пустой, показываем приглашение начать поиск. Второй - запрос есть, но ничего не найдено, показываем сообщение об отсутствии результатов. Третий - есть результаты, показываем список. Каждое состояние даёт пользователю чёткую обратную связь о том, что происходит.
Мы используем map для отображения всех найденных стран. В отличие от suggestions, здесь нет ограничения на количество - показываем всё, что нашли. Каждая страна получает уникальный key по id для корректной работы React. Структура включает флаг, название и детальную информацию.