所以至少对我来说,我正在处理一个相当复杂的问题。在这里,我有基本的购物车功能(添加、删除等...)。我面临的问题是这样的。所以我可以将一个项目添加到购物车,但是当我尝试将不同的项目添加到购物车时,它并没有这样做。当我尝试添加我之前添加的相同项目时,它正在改变购物车项目的数量,所以这是一种工作。我在结帐组件中遇到总计问题,它显示 NaN 而不是总价格。我知道这是一段相当长的代码,如果有人能指出我的错误,我将不胜感激。谢谢
上下文 API
import React from "react";
function getCartFromLocalStorage() {
return localStorage.getItem("cart")
? JSON.parse(localStorage.getItem("cart"))
: [];
}
const CartContext = React.createContext({});
function CartProvider({ children }) {
const [cart, setCart] = React.useState(getCartFromLocalStorage());
const [total, setTotal] = React.useState(0);
const [cartItems, setCartItems] = React.useState(0);
function onUpdate() {
localStorage.setItem("cart", JSON.stringify(cart));
// total
let newTotal = cart.reduce((total, cartItem) => {
return (total += cartItem.amount * cartItem.RegularPrice);
}, 0);
newTotal = parseFloat(newTotal.toFixed(3));
setTotal(newTotal);
// cartItems
let newCartItems = cart.reduce((total, cartItem) => {
return (total += cartItem.amount);
}, 0);
setCartItems(newCartItems);
}
React.useEffect(onUpdate, [cart]);
// remove
const removeItem = (key) => {
setCart([...cart].filter((item) => item.key !== key));
};
// addToCart
const addToCart = (book) => {
const { key, image, bookName, by, RegularPrice } = book;
let item = cart.find((item) => item.key === key);
if (item) {
item.amount++;
onUpdate();
} else {
setCart(
cart.concat({
amount: 1,
price: book.RegularPrice,
...book
})
);
}
};
const clearCart = () => {
setCart([]);
};
return (
<CartContext.Provider
value={{
cart,
cartItems,
total,
removeItem,
addToCart,
clearCart
}}
>
{children}
</CartContext.Provider>
);
}
export { CartContext, CartProvider };
购物车链接
import React from "react";
import { Link } from "react-router-dom";
import {FiShoppingCart} from 'react-icons/fi'
import { CartContext } from "../../context/cart";
export default function CartLink() {
const { cartItems} = React.useContext(CartContext);
return (
<div className="cartlink__container">
<Link to="/cart">
<FiShoppingCart />
</Link>
<span className="cartlink__total">{cartItems}</span>
</div>
);
}
购物车项目
import React, { useContext } from "react";
import { CartContext } from "../../context/cart";
import Checkout from "./Checkout";
export default function CartItem({ key, image,bookName, RegularPrice, by, amount }) {
const {removeItem} = useContext(CartContext)
return (
<div key={key} className="cart__item">
<img className='cart__image' src={image} />
<div className='cart__itemdesc'>
<h4>{bookName}</h4>
<h6 className='cart__by'>By: {by}</h6>
<button
className="cart__removebtn"
onClick={() => {
removeItem(key);
}}
>
Remove
</button>
</div>
<span className='circle'><span className='circleone'></span></span>
<span>{RegularPrice}</span>
<div>
<Checkout />
</div>
</div>
);
}
结帐
import React,{useContext} from 'react'
import { CartContext } from '../../context/cart'
import {Link, useHistory } from 'react-router-dom'
import EmptyCart from './EmptyCart';
const Checkout = () => {
const history = useHistory()
const {cart, total} = useContext(CartContext)
if (cart.length === 0) {
return <EmptyCart />;
}
return (
<div>
<Link to='/stripecontainer' className='checkout__btnOne'>Proceed to
Checkout</Link>
<h2>total : ${total}</h2>
</div>
)
}
export default Checkout
import React,{useState, useEffect, useContext} from 'react'
import './Home.css'
import Books from './Books'
import { BookContext } from "../../context/books";
const Home = () => {
const {data, handleSelectCategory, currentSelectedCategory } =useContext(BookContext)
return (
<div className='books__container' >
<h1 className='categories'>Categories</h1>
{Object.keys(data).map((key, index)=>{
let books = data[key];
return (
<>
<span key={key} onClick={() => handleSelectCategory(key)} className='books__list' >
{books[0].category}
</span>
</>
);})}
<Books category={currentSelectedCategory} />
</div>
)
}
export default Home
答案 0 :(得分:2)
您在计算 newTotal
时有两个问题。
price
中每一项的 cart
是一个 string
,如 "$17.47"
。对该 string
进行数学运算返回 NaN
。你真的应该在这里存储一个 number
。作为解决方法,您可以使用 parseFloat
,但您需要先删除 $
,因为 parseFloat("$17.47")
是 NaN
。
你同时分配和返回。您只想return
新值。所以不要使用 +=
。
const newTotal = cart.reduce((total, cartItem) => {
return total + cartItem.amount * parseFloat(cartItem.price.replace('$', ''));
}, 0);
setTotal(newTotal);
关于非唯一键:您使用的属性 book.key
似乎不存在 in your data set。这也使您无法从购物车中删除商品或购物车中有多个不同的商品,因为您是根据此不存在的 key
进行匹配的。这些书籍确实有一个独特的属性 id
,您应该将其用作 JSX 中的 key
属性和过滤数组。
item.amount++;
中的 addToCart
是状态的突变。您需要用复制的对象替换 item
。
setCart(
cart.map((item) =>
item.id === book.id ? { ...item, amount: item.amount + 1 } : item
)
);
total
和 cartItems
可以从 cart
的状态派生,所以它们并不需要是它们自己的状态。
感谢您提供 CodeSandbox。当我可以运行您的代码时,更容易找到您的问题。
答案 1 :(得分:0)
我不熟悉 JSon,但如果您在最后得到 NaN,那么尝试一个简单的测试,将所有值打印到屏幕上以跟踪问题开始的位置(弹出意外值的位置)。>
至于购物车项目,您说您只能将同一项目添加到列表中,然后在将其添加到购物车之前尝试打印第二个项目。这可能是一个参考问题。
答案 2 :(得分:0)
我认为 NaN
即将到来是因为 RegularPrice
属性被移动到 price
中的 addToCart
但随后 RegularPrice
用于 {{} {1}}。