【问题标题】:TotalPrice of the cart is displaying NaN购物车的 TotalPrice 显示 NaN
【发布时间】:2021-03-29 20:47:15
【问题描述】:

因此,至少对我来说,我正在处理一个相当复杂的问题。在这里,我有基本的购物车功能(添加、删除等)。我面临的问题是这样的。所以我可以将一个项目添加到购物车,但是当我尝试将不同的项目添加到购物车时它没有这样做。当我尝试添加我之前添加的相同项目时,它正在改变购物车项目的数量,所以这是一种工作。我在结帐组件中的总计有问题,它显示的是 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

【问题讨论】:

  • let newCartItems = cart.reduce((total, cartItem) =&gt; { return (total += cartItem.amount); }, 0); setCartItems(newCartItems); 使用单个号码调用setCartItems,这可能是您想要的,但听起来很奇怪。我希望setCartItems 采用 CartItem 对象的数组...
  • 在购物车项下:&lt;button className="cart__removebtn" onClick={() =&gt; { removeItem(key); }}&gt; 看起来很可疑...通常 html 事件侦听器被包裹在"... 所以如果这不会导致不相关的问题,我想我学到了一些新东西今天。
  • @ShanerM13 我想你学到了一些新东西。
  • @异端猴还是一样
  • @ShanerM13 请求并发布 CodeSandbox 完全没问题。问题是提问者只是链接到 CodeSandbox 并且没有在他们的问题正文中包含相关代码。

标签: javascript node.js reactjs redux react-context


【解决方案1】:

newTotal的计算有两个问题。

  1. cart 中每个项目的pricestring,例如"$17.47"。对该string 进行数学运算会返回NaN。你真的应该在这里存储number。作为一种解决方法,您可以使用parseFloat,但您需要先删除$,因为parseFloat("$17.47")NaN

  2. 您同时分配和返回。您只想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属性和过滤数组。


addToCart 中的 item.amount++; 是状态的突变。您需要将item 替换为复制的对象。

setCart(
  cart.map((item) =>
    item.id === book.id ? { ...item, amount: item.amount + 1 } : item
  )
);

totalcartItems 可以从cart 的状态派生出来,所以它们并不需要成为自己的状态。


感谢您提供 CodeSandbox。当我可以运行您的代码时,找到您的问题就容易多了。

【讨论】:

  • 它给了我TypeError: Cannot read property 'replace' of undefined的错误
  • CartProviderBookProvider 内部,所以如果你愿意,你可以只存储 id 和数量的键控对象,如 {"3": 1, "5": 2},以及通过查找可以获得的所有其他信息id 的书。
  • 改变的是,现在我可以添加不同的项目,但是由于某些奇怪的原因,当我按下删除一项时,它会全部清除
  • 这不是为我做的。
【解决方案2】:

我对 JSon 不熟悉,但如果最后得到的是 NaN,请尝试一个简单的测试,将所有值打印到屏幕上,以跟踪问题开始的位置(弹出意外值的位置)。

至于购物车项目,您说您只能将相同的项目添加到列表中,然后在将第二个项目添加到购物车之前尝试打印第二个项目。这可能是一个参考问题。

【讨论】:

  • 我可以添加一个(图片,作者,书名),但购物车商品的数量正在变化
【解决方案3】:

我认为NaN 即将到来,因为RegularPrice 属性已移至addToCart 中的price,但随后RegularPrice 用于onUpdate 中的缩减功能。

【讨论】:

  • 还是一样
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-31
  • 2012-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多