我正在一家电子商务商店工作,我已经设置了一个具有唯一 id 的产品页面,并循环遍历这些项目来显示它们,但在结账页面上,当我尝试删除某个项目时,我突然得到了一个 nan 值。这是我从中提取项目作为测试的页面。
这是填充购物车中的商品的产品页面,但如果购物车中有 2 个或更多商品,当我从购物车中删除商品时,我会收到唯一键错误。 下面是购物车页面,显示购物车中的商品
我已经为密钥提供了产品的唯一标识符,但现在我收到一个新错误“警告:列表中的每个子项都应该有一个唯一的“key”属性。当我删除项目时,这会导致购物车中出现 nan 。 ” 我有点卡在这里了。
import * as React from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';
import Modal from '@mui/material/Modal';
import products from './product'
import { useContext } from 'react';
import { useState, useEffect} from 'react';
import cart from '../context/cart'
import { CartContext } from '../context/cart';
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: "100%",
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4,
};
export default function BasicModal() {
const [open, setOpen] = React.useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
const { cartItems, addToCart, removeFromCart, clearCart, getCartTotal } = useContext(CartContext)
useEffect(() => {
// storing input name
localStorage.getItem("cartItems", JSON.stringify(cartItems));
}, [cartItems])
// payment is processed here
return (
<div>
<Button onClick={handleOpen} >
({cartItems.length})
Check Out</Button>
<Modal
disableScrollLock={true}
fullScreen={true}
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
<>
<div className="flex-col flex items-center bg-white gap-8 p-10 text-black text-sm">
<h1 className="text-2xl font-bold">Cart</h1>
<div className="flex flex-col gap-4">
{cartItems.map((item) => (
<div className="flex justify-between items-center" key={products.id}>
<div className="flex gap-4">
<img src={item.imageId} key="2014" alt={item.title} className="rounded-md h-24" />
<div className="flex flex-col">
<h1 className="text-lg font-bold" key="2015">{item.title}</h1>
<p className="text-gray-600" key="2013">{item.price}</p>
<p className="text-gray-600" key="202">{item.description}</p>
</div>
</div>
<div className="flex gap-4">
<button
className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
onClick={() => {
addToCart(item)
}}
>
+
</button>
<p>{item.quantity}</p>
<button
className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
onClick={() => {
removeFromCart(item)
}}
>
-
</button>
</div>
</div>
))}
</div>
{
cartItems.length > 0 ? (
<div className="flex flex-col justify-between items-center">
<h1 className="text-lg font-bold">Total: ${getCartTotal()}</h1>
<button
className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
onClick={() => {
clearCart()
}}
>
Clear cart
</button>
{/* check out here */}
{/* <Button variant="primary" onClick={} >Check out
</Button> */}
</div>
) : (
<>
<h1 className="text-lg font-bold">Your cart is empty</h1>
</>
)
}
</div>
<div class="col d-flex justify-content-center">
</div>
</>
</Box>
</Modal>
</div>
);
}
这就是我的背景
import { createContext, useState, useEffect } from 'react'
import React from 'react'
import products from '../components/product';
export const CartContext = createContext()
export const CartProvider = ({ children }) => {
const [cartItems, setCartItems] = useState(localStorage.getItem('cartItems') ? JSON.parse(localStorage.getItem('cartItems')) : [0])
const addToCart = (item) => {
const isItemInCart = cartItems.find((cartItem) => cartItem.id === item.id);
if (isItemInCart) {
setCartItems(
cartItems.map((cartItem) =>
cartItem.id === item.id
? { ...cartItem, quantity: cartItem.quantity + 1 }
: cartItem
)
);
} else {
setCartItems([...cartItems, { ...item, quantity: 1 }]);
}
};
const removeFromCart = (item) => {
const isItemInCart = cartItems.find((cartItem) => cartItem.id === item.id);
if (isItemInCart && isItemInCart.quantity === 1) {
setCartItems(cartItems.filter((cartItem) => cartItem.id !== item.id));
} else {
setCartItems(
cartItems.map((cartItem) =>
cartItem.id === item.id
? { ...cartItem, quantity: cartItem.quantity - 1 }
: 0,
)
);
}
};
const clearCart = () => {
setCartItems([]);
};
const getCartTotal = () => {
// cart item total is being added here
return cartItems.reduce((total, cartItem) => total + cartItem.price * cartItem.quantity, 0);
};
useEffect(() => {
localStorage.setItem("cartItems", JSON.stringify(cartItems));
}, [cartItems]);
useEffect(() => {
const cartItems = localStorage.getItem("cartItems");
if (cartItems) {
setCartItems(JSON.parse(cartItems));
}
}, []);
const initialValue = 0;
const total = cartItems.reduce((accumulator,current) => accumulator + current.price * current.quantity, initialValue)
return (
<CartContext.Provider
value={{
cartItems,
addToCart,
removeFromCart,
clearCart,
getCartTotal,
}}
>
{children}
</CartContext.Provider>
);
};
我该如何解决这个问题。
如果购物车中有超过 2 件商品,每当我从购物车中删除商品时,我都会收到一个 nan 错误。不确定如何解决这个问题。
{cartItems.map((item) => (
<div className="flex justify-between items-center" key={products.id}>
<div className="flex gap-4">
<img src={item.imageId} key="2014" alt={item.title} className="rounded-md h-24" />
<div className="flex flex-col">
<h1 className="text-lg font-bold" key="2015">{item.title}</h1>
<p className="text-gray-600" key="2013">{item.price}</p>
<p className="text-gray-600" key="202">{item.description}</p>
</div>
目前这是我当前的错误index.js:1210警告:列表中的每个子项都应该有一个唯一的“key”属性。
检查
BasicModal
的渲染方法。
通过为地图中的每个项目添加唯一的键,我最终解决了这个问题。
这是购物车的上下文。
import { createContext, useState, useEffect } from 'react'
import React from 'react';
export const CartContext = createContext()
export const CartProvider = ({ children }) => {
const [cartItems, setCartItems] = useState(localStorage.getItem('cartItems') ? JSON.parse(localStorage.getItem('cartItems')) : [])
const addToCart = (item) => {
const isItemInCart = cartItems.find((cartItem) => cartItem.id === item.id);
if (isItemInCart) {
setCartItems(
cartItems.map((cartItem) =>
cartItem.id === item.id
? { ...cartItem, quantity: cartItem.quantity + 1 }
: cartItem
)
);
} else {
setCartItems([...cartItems, { ...item, quantity: 1 }]);
}
};
const removeFromCart = (item) => {
const isItemInCart = cartItems.find((cartItem) => cartItem.id === item.id);
if (isItemInCart.quantity === 1) {
setCartItems(cartItems.filter((cartItem) => cartItem.id !== item.id));
} else {
setCartItems(
cartItems.map((cartItem) =>
cartItem.id === item.id
? { ...cartItem, quantity: cartItem.quantity - 1 }
: cartItem
)
);
}
};
const clearCart = () => {
setCartItems([]);
};
const getCartTotal = () => {
return cartItems.reduce((total, item) => total + item.price * item.quantity, 0);
};
useEffect(() => {
localStorage.setItem("cartItems", JSON.stringify(cartItems));
}, [cartItems]);
useEffect(() => {
const cartItems = localStorage.getItem("cartItems");
if (cartItems) {
setCartItems(JSON.parse(cartItems));
}
}, []);
return (
<CartContext.Provider
value={{
cartItems,
addToCart,
removeFromCart,
clearCart,
getCartTotal,
}}
>
{children}
</CartContext.Provider>
);
};
这是结帐购物车的更新代码
import * as React from 'react';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import axios from 'axios';
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
import { CartContext } from '../context/cart';
import Axios from 'axios';
import { useContext } from 'react';
import { useState, useEffect} from 'react';
export default function AlertDialog() {
const [open, setOpen] = React.useState(false);
const { cartItems, addToCart, removeFromCart, clearCart, getCartTotal } = useContext(CartContext)
useEffect(() => {
// storing input name
localStorage.getItem("cartItems", JSON.stringify(cartItems));
}, [cartItems])
const handleCheckout = () => {
;
};
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: "100%",
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4,
};
return (
<React.Fragment>
<Button variant="outlined" onClick={handleClickOpen}>
Confirm check out here
</Button>
<Dialog
open={open}
disableScrollLock={false}
fullScreen={true}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">
{"Cofirm check out here?"}
</DialogTitle>
<DialogContent>
<Box sx={style}>
<>
<div className="flex-col flex items-center bg-white gap-8 p-10 text-black text-sm">
<h1 className="text-2xl font-bold">Cart</h1>
<div className="flex flex-col gap-4">
{cartItems.map((item) => (
<div className="flex justify-between items-center" key={item.id} id={item.id}>
<div className="flex gap-4">
<img src={item.imageId} key={item.imageId } alt={item.title} className="rounded-md h-24" />
<div className="flex flex-col">
<h1 className="text-lg font-bold" key={item.title } >{item.title} </h1>
<p className="text-gray-600" key={item.price } > {item.price}</p>
<p className="text-gray-600"key={item.description }>{item.description} </p>
</div>
</div>
<div className="flex gap-4">
<button
className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
onClick={() => {
addToCart(item)
}}
>
+
</button>
<p >{item.quantity}</p>
<button
className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
onClick={() => {
removeFromCart(item)
}}
>
-
</button>
</div>
</div>
))}
</div>
{
cartItems.length > 0 ? (
<div className="flex flex-col justify-between items-center">
<h1 className="text-lg font-bold">Total: ${getCartTotal()}</h1>
<button
className="px-4 py-2 bg-gray-800 text-white text-xs font-bold uppercase rounded hover:bg-gray-700 focus:outline-none focus:bg-gray-700"
onClick={() => {
clearCart()
}}
>
Clear cart
</button>
{/* check out here */}
{/* check out here */}
{/* <Button variant="primary" onClick={} >Check out
</Button> */}
</div>
) : (
<>
<h1 className="text-lg font-bold">Your cart is empty</h1>
</>
)
}
</div>
<div class="col d-flex justify-content-center">
</div>
</>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Close Check Out</Button>
<Button onClick={handleCheckout} autoFocus>
Check out and pay
</Button>
</DialogActions>
</Dialog>
</React.Fragment>
);
}