Видеоуроки, интерактивный редактор и сохранение прогресса — бесплатно, сразу после входа.
ВойтиСоздать аккаунт — бесплатноЗакончили урок?
Войдите, чтобы отмечать прогресс
В этом решении мы создаём полнофункциональную корзину интернет-магазина с добавлением, изменением количества и подсчётом итоговой суммы.
Корзина - это массив товаров. Каждый элемент содержит все поля оригинального товара плюс дополнительное поле quantity (количество). Начальное значение - пустой массив, потому что корзина изначально пуста.
Метод find ищет первый элемент, для которого функция вернула true. Мы проверяем совпадение по id - уникальному идентификатору товара. Если товар найден, existingItem содержит этот объект. Если не найден - undefined. Это позволяет определить, добавлять новый товар или увеличивать количество существующего.
Если товар уже в корзине, мы создаём новый массив с помощью map, увеличивая quantity только для нужного товара. Если товара нет, добавляем его в конец массива через spread оператор [...cart, newItem]. Оператор ...product копирует все поля товара, а затем мы добавляем quantity: 1.
Метод map создаёт новый массив. Для товара с нужным id мы создаём новый объект - копируем все поля через ...item и перезаписываем quantity. Для остальных товаров возвращаем их без изменений. React видит, что массив новый, и перерисовывает компонент. Важно не мутировать оригинальный массив - это нарушает правила React.
Math.max(1, item.quantity - 1) выбирает большее из двух значений. Если quantity равно 2, 2 - 1 = 1, и Math.max(1, 1) = 1. Если quantity равно 1, 1 - 1 = 0, но Math.max(1, 0) = 1. Это гарантирует, что количество никогда не станет меньше 1. Для полного удаления используется отдельная кнопка.
Метод filter создаёт новый массив, содержащий только элементы, для которых функция вернула true. Условие item.id !== productId означает "все товары, кроме удаляемого". Товар с нужным id не попадёт в новый массив - он удалён.
Метод reduce агрегирует массив в одно значение. Он принимает функцию и начальное значение аккумулятора (0). Функция получает аккумулятор sum и текущий элемент item, возвращает новое значение аккумулятора. Для каждого товара мы добавляем его quantity к общей сумме. Если в корзине 2 ноутбука и 3 мыши, результат будет 5.
Здесь reduce суммирует стоимость всех товаров. Для каждого товара мы умножаем цену на количество и добавляем к общей сумме. Например, 2 товара по 1000₽ и 1 товар по 500₽ дадут (1000 * 2) + (500 * 1) = 2500₽. Это промежуточная сумма без доставки.
Доставка стоит 500₽, только если в корзине есть товары. Проверка cart.length > 0 возвращает true для непустой корзины. Тернарный оператор выбирает 500 или 0. Это предотвращает показ стоимости доставки для пустой корзины.
Простое сложение суммы товаров и доставки. Все вычисления totalItems, subtotal, shipping и total - это не состояния, а вычисляемые значения. Они автоматически пересчитываются при каждом рендере, когда меняется cart.
Функция устанавливает корзину в пустой массив. Мы вызываем её после оформления заказа, чтобы пользователь мог начать новые покупки с чистой корзины.
Двойное использование spread оператора. Внешний ...cart разворачивает существующие элементы корзины. Внутренний ...product копирует все поля товара из каталога. Затем мы добавляем новое поле quantity: 1. Без копирования мы бы мутировали оригинальный объект товара из PRODUCTS, что могло бы вызвать баги.
Проверяем длину массива корзины. Если 0 - показываем дружелюбное сообщение о пустой корзине. Иначе рендерим список товаров и итоговую информацию. Фрагмент <>...</> позволяет вернуть несколько элементов без добавления лишнего div в DOM.
Рядом с заголовком показываем количество товаров в виде бейджа. Оператор && рендерит бейдж только когда есть товары. Если корзина пуста, totalItems равно 0, условие ложно, и бейдж не отображается. Это визуальная подсказка о состоянии корзины.
Мы используем map для отображения каждого товара из корзины. В отличие от каталога, здесь мы показываем item.quantity и предоставляем элементы управления для изменения количества. Каждый товар получает уникальный key по id.
Пользователь может увеличить, уменьшить количество или полностью удалить товар. Кнопки "-" и "+" изменяют quantity, кнопка "Удалить" убирает товар из корзины. Все три функции принимают id товара для идентификации, какой элемент изменять.
При клике показываем уведомление с суммой заказа и очищаем корзину. toLocaleString() форматирует число с разделителями разрядов. В реальном приложении здесь был бы запрос к серверу для сохранения заказа, но для учебного примера достаточно alert и очистки корзины.
Метод toLocaleString() добавляет пробелы для разделения тысяч. Цена 75000 превращается в "75 000", что намного читабельнее. Формат зависит от локали браузера - в русской версии будет пробел, в английской - запятая.