购物车的 TotalPrice 显示为 NaN
TotalPrice of the cart is displaying NaN
所以我正在处理一个相当复杂的问题,至少对我来说是这样。这里我有基本的购物车功能(添加、删除等...)。我面临的问题是这样的。所以我能够将一个项目添加到购物车,但是当我尝试将不同的项目添加到购物车时它没有这样做。当我尝试添加我之前添加的相同项目时,它正在改变购物车项目的数量,所以这是一种工作。我在结帐组件中遇到总计问题,它显示的是 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
我不熟悉 JSon,但是如果您最后得到的是 NaN,那么请尝试一个简单的测试,将所有值打印到屏幕上,以跟踪问题的开始位置(出现意外值的地方)弹出)。
至于购物车商品,你说你只能将相同的商品添加到列表中,然后尝试在将其添加到购物车之前打印第二个商品。可能是个参考问题。
我认为 NaN
即将到来,因为 RegularPrice
属性 在 addToCart
中移到了 price
,但随后使用了 RegularPrice
在 onUpdate
.
的缩减函数中
你在newTotal
的计算中有两个问题。
cart
中每个项目的 price
与 ".47"
类似 string
。对 string
returns NaN
进行数学运算。你真的应该在这里存储一个 number
。作为解决方法,您可以使用 parseFloat
,但您需要先删除 $
,因为 parseFloat(".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
进行匹配的。书籍 do 有一个独特的 属性 id
,你应该使用它作为你的 JSX 中的 key
属性 和过滤数组。
addToCart
中的item.amount++;
是状态突变。您需要用复制的对象替换 item
。
setCart(
cart.map((item) =>
item.id === book.id ? { ...item, amount: item.amount + 1 } : item
)
);
total
和cartItems
可以从cart
的状态推导出来,所以它们并不一定是自己的状态。
感谢您提供 CodeSandbox。当我可以 运行 你的代码时,找到你的问题就容易多了。
所以我正在处理一个相当复杂的问题,至少对我来说是这样。这里我有基本的购物车功能(添加、删除等...)。我面临的问题是这样的。所以我能够将一个项目添加到购物车,但是当我尝试将不同的项目添加到购物车时它没有这样做。当我尝试添加我之前添加的相同项目时,它正在改变购物车项目的数量,所以这是一种工作。我在结帐组件中遇到总计问题,它显示的是 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
我不熟悉 JSon,但是如果您最后得到的是 NaN,那么请尝试一个简单的测试,将所有值打印到屏幕上,以跟踪问题的开始位置(出现意外值的地方)弹出)。
至于购物车商品,你说你只能将相同的商品添加到列表中,然后尝试在将其添加到购物车之前打印第二个商品。可能是个参考问题。
我认为 NaN
即将到来,因为 RegularPrice
属性 在 addToCart
中移到了 price
,但随后使用了 RegularPrice
在 onUpdate
.
你在newTotal
的计算中有两个问题。
cart
中每个项目的price
与".47"
类似string
。对string
returnsNaN
进行数学运算。你真的应该在这里存储一个number
。作为解决方法,您可以使用parseFloat
,但您需要先删除$
,因为parseFloat(".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
进行匹配的。书籍 do 有一个独特的 属性 id
,你应该使用它作为你的 JSX 中的 key
属性 和过滤数组。
addToCart
中的item.amount++;
是状态突变。您需要用复制的对象替换 item
。
setCart(
cart.map((item) =>
item.id === book.id ? { ...item, amount: item.amount + 1 } : item
)
);
total
和cartItems
可以从cart
的状态推导出来,所以它们并不一定是自己的状态。
感谢您提供 CodeSandbox。当我可以 运行 你的代码时,找到你的问题就容易多了。