Видеоуроки, интерактивный редактор и сохранение прогресса — бесплатно, сразу после входа.
ВойтиСоздать аккаунт — бесплатноЗакончили урок?
Войдите, чтобы отмечать прогресс
В этом решении мы создаём систему фильтрации товаров по нескольким критериям одновременно.
Мы создаём отдельное состояние для каждого фильтра. category хранит выбранную категорию, по умолчанию 'all' означает "все категории". Для цен и поиска используем пустые строки - это позволяет понять, применён фильтр или нет. Пустая строка означает, что фильтр не активен.
Метод filter проверяет каждый товар по всем критериям. Мы создаём отдельную булеву переменную для каждого условия - это делает код читаемым и понятным. Товар попадает в результат только если все условия истинны (все переменные matches... равны true).
Оператор ! (НЕ) превращает пустую строку в true. Если minPrice пустое, !minPrice будет true, и оператор || (ИЛИ) вернёт true без проверки второго условия. Если minPrice заполнено, проверяем цену товара. Это паттерн "если фильтр не задан, то он выполнен".
Input с type="number" всё равно возвращает строку через e.target.value. Функция Number() преобразует строку в число для корректного сравнения. Без этого сравнение 45000 >= "50000" работало бы как сравнение строк, что дало бы неверный результат.
Метод toLowerCase() переводит строку в нижний регистр. Мы применяем его к названию товара и к поисковому запросу, чтобы поиск не зависел от регистра - "ноутбук", "Ноутбук" и "НОУТБУК" дадут одинаковый результат. Метод includes() проверяет, содержится ли подстрока в строке.
Элемент <select> работает как контролируемый компонент через value и onChange. Атрибут value на <select> (не на <option>) определяет выбранную опцию. Когда пользователь выбирает другую опцию, onChange обновляет состояние.
type="number" добавляет стрелки для изменения значения и позволяет вводить только цифры. Атрибут placeholder показывает подсказку в пустом поле. Несмотря на тип number, значение всё равно приходит как строка, поэтому позже нужно преобразование с Number().
Функция возвращает все фильтры к начальным значениям. Мы вызываем все функции обновления состояния подряд. React умный - он объединит эти обновления в одну перерисовку, а не будет рендерить компонент четыре раза.
Мы показываем количество найденных товаров и общее количество. filteredProducts.length автоматически обновляется при изменении фильтров, потому что filteredProducts пересчитывается при каждом рендере. Это помогает пользователю понять, насколько сузился поиск.
Когда фильтры слишком строгие и товаров не найдено, вместо пустой сетки показываем дружелюбное сообщение. Пользователь сразу понимает, что проблема не в загрузке данных, а в фильтрах, и знает, что делать дальше.
Метод toLocaleString() форматирует число с разделителями разрядов. Цена 45000 превращается в 45 000, что гораздо удобнее читать. Формат зависит от локали браузера пользователя.