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个项目语句变成12个,或者更确切地说,1个用于一个项目,2个用于我想购买的另一个项目。出于某种原因,当他们应该显示3而不是12时,他们不会组合。
确保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