#javascript #reactjs #react-redux
#javascript #reactjs #реагировать-redux
Вопрос:
import React, { useEffect } from "react";
import { addToCart, removeFromCart } from "../actions/cartActions";
import { useDispatch, useSelector } from "react-redux";
import { Link } from "react-router-dom";
function CartScreen(props) {
const cart = useSelector((state) => state.cart);
const { cartItems } = cart;
const productId = props.match.params.id;
const qty = props.location.search
? Number(props.location.search.split("=")[1])
: 1;
const dispatch = useDispatch();
const removeFromCartHandler = (productId) => {
dispatch(removeFromCart(productId));
};
useEffect(() => {
if (productId) {
dispatch(addToCart(productId, qty));
}
}, []);
const checkoutHandler = () => {
props.history.push("/signin?redirect=shipping");
};
return (
<div className="cart">
<div className="cart-list">
<ul className="cart-list-container">
<li>
<h3>Shopping Cart</h3>
<div>Price</div>
</li>
{cartItems.length === 0 ? (
<div>Cart is empty</div>
) : (
cartItems.map((item) => (
<li>
<div className="cart-image">
<img src={item.image} alt="product" />
</div>
<div className="cart-name">
<div>
<Link to={"/product/" item.product}>{item.name}</Link>
</div>
<div>
Qty:
<select
value={item.qty}
onChange={(e) =>
dispatch(addToCart(item.product, e.target.value))
}
>
{[...Array(item.countInStock).keys()].map((x) => (
<option key={x 1} value={x 1}>
{x 1}
</option>
))}
</select>
<button
type="button"
className="button"
onClick={() => removeFromCartHandler(item.product)}
>
Delete
</button>
</div>
</div>
<div className="cart-price">${item.price}</div>
</li>
))
)}
</ul>
</div>
<div className="cart-action">
<h3>
Subtotal ( {cartItems.reduce((a, c) => a c.qty, 0)} items) : ${" "}
{cartItems.reduce((a, c) => a c.price * c.qty, 0)}
</h3>
<button
onClick={checkoutHandler}
className="button primary full-width"
disabled={cartItems.length === 0}
>
Proceed to Checkout
</button>
</div>
</div>
);
}
export default CartScreen;
Основная цель этого кода — отобразить веб-страницу по имени экрана корзины.
Внутри экрана корзины находятся все товары, которые я хочу купить с другой страницы, взятые из другого js-файла, в котором указаны все даты для этих товаров.
Я хочу выделить этот конкретный код прямо здесь.
<h3>
Subtotal ( {cartItems.reduce((a, c) => a c.qty, 0)} items) : ${" "}
{cartItems.reduce((a, c) => a c.price * c.qty, 0)}
</h3>
Способ работы этого кода:
Промежуточный итог подсчитывает, сколько всего товаров у меня есть в корзине, а затем берет стоимость каждого продукта и умножает ее на их количество, прежде чем добавлять все и сообщать мне, сколько стоит все, что я хочу купить, прежде чем я захочу это купить. Раздел «Общая цена» работает абсолютно нормально.
Что меня озадачивает, так это то, что промежуточный итог количества товаров в корзине, похоже, не работает так, как я намереваюсь.
Это работает нормально, если у меня просто есть 2 отдельных товара в корзине, из которых я хочу купить 1, в котором промежуточный итог сообщает мне, что у меня в общей сложности 2 товара в корзине, что правильно. Но как только я хочу купить 2 из одного элемента, промежуточный итог каким-то образом превращается из предыдущего утверждения 2 item в 12 или, скорее, 1 для одного элемента и 2 для другого элемента, который я хочу купить 2. По какой-то причине они не объединяются, когда они должны показывать 3, а не 12.
Ответ №1:
Убедитесь, что ваши qty
price
свойства и являются не строками, а числами. Если вы сохраните эти значения в виде чисел, ваши .reduce()
методы будут работать должным образом:
const cartItems = [
{ qty: 1, price: 5.99 },
{ qty: 2, price: 25.0 },
{ qty: 5, price: 10.0 },
];
cartItems.reduce((a, c) => a c.qty, 0);
// => 8
cartItems.reduce((a, c) => a c.price * c.qty, 0);
// => 105.99
Если вы используете
оператор с числами, он суммирует их, как и следовало ожидать. Однако, если вы сохраните свои числа в виде строк и попытаетесь вычислить их сумму, это фактически объединит их в новую строку.
Если вы используете *
оператор, вы неявно преобразуете строки в числа, и именно поэтому общая цена работает, а общее количество элементов — нет:
const cartItems = [
{ qty: '1', price: '5.99' },
{ qty: '2', price: '25.00' },
{ qty: '5', price: '10.00' },
];
cartItems.reduce((a, c) => a c.qty, 0);
// => "0125"
cartItems2.reduce((a, c) => a c.price * c.qty, 0);
// => 105.99
Чтобы исправить это, вам нужно либо убедиться, что вы сохраняете qty
и price
как числа, либо преобразовать их в свой .reduce()
.
const cartItems = [
{ qty: '1', price: '5.99' },
{ qty: '2', price: '25.00' },
{ qty: '5', price: '10.00' },
];
cartItems.reduce((a, c) => a Number(c.qty), 0);
// => 8