"use client"
import Container from "@/components/Container";
import ProductDetails from "./ProductDetails";
import ListRating from "./ListRating";
import { products } from "@/utils/products";
interface IParams {
productId?: string;
}
const Product = ({ params }: { params: IParams }) => {
console.log('params:', params);
const product = products.find((item) => item.id === params.productId);
if (!product) {
// Handle product not found case
return <div>Product not found</div>;
}
return (
<div className="p-8">
<Container>
<ProductDetails product={product} />
</Container>
</div>
);
};
export default Product;
所以这是旨在帮助我获取产品数据的代码,但这是我不断收到的错误
⨯ TypeError: Cannot read properties of undefined (reading 'id')
at ProductDetails (./app/products/[productid]/ProductDetails.tsx:31:21)
34 |
35 | const [CartProduct,setcartProduct]= useState<CartProductType>({
> 36 | id: product.id,
| ^
37 | name: product.name,
38 | description: product.id,
39 | category:product.category,
然后我决定添加 if 条件,现在我看到的是当我单击该项目时未找到产品
"use client"
import Button from "@/components/products/Button";
import ProductImages from "@/components/products/productImages";
import SetColor from "@/components/products/setColour";
import SetQuantity from "@/components/products/setQuantity";
import { UseCart } from "@/hook/useCart";
import { Rating } from "@mui/material";
import { useRouter } from "next/navigation";
import { useCallback, useState, useEffect } from "react";
import {BsFillCheckCircleFill} from 'react-icons/bs';
interface ProductDetailsProps{
product:any
}
export type CartProductType= {
id:string,
name:string,
description:string,
category:string,
brand:string,
selectedImg:SelectedImgType,
quantity:number,
price:number
}
export type SelectedImgType={
color:string,
colorCode:string,
image: string
}
const ProductDetails:React.FC<ProductDetailsProps> = ({product}) => {
const [CartProduct,setcartProduct]= useState<CartProductType>({
id: product.id,
name: product.name,
description: product.id,
category:product.category,
brand:product.brand,
selectedImg:{...product.images[0]},
quantity: 1,
price:product.price
});
const {handleAddProductCart,cartProducts} = UseCart();
const [isProductinCart,setIsProductinCart]= useState(false);
const router= useRouter();
const Horizontal = ()=>{
return (<hr className=" w-1/2 my-2"/>)
}
const{cartTotalQty}= UseCart()
useEffect(() => {
console.log(CartProduct);
}, [CartProduct]);
console.log(cartProducts)
useEffect(()=>{
setIsProductinCart(false)
if (cartProducts) {
const existingIndex= cartProducts.findIndex((item)=>item.id ===product.id)
if (existingIndex > -1){
setIsProductinCart(true)
}
}
},[cartProducts])
const ProductRating = product.reviews.reduce((acc:number,item:any)=>item.rating + acc,0) / product.reviews.length
const handleColorSelect=useCallback((value:SelectedImgType)=>{
setcartProduct((prev)=>{
return {...prev,selectedImg:value}
})
},[CartProduct.selectedImg])
const handleQuantityInc= useCallback(()=>{
setcartProduct((prev)=>{
if (prev.quantity<99){
return{...prev, quantity: prev.quantity + 1}
}
return prev;
})
},[CartProduct])
const handleQuantityDec = useCallback(() => {
setcartProduct((prev) => {
if (prev.quantity > 1) {
return { ...prev, quantity: prev.quantity - 1 };
}
return prev;
});
}, [CartProduct]);
return (
<div className="grid grid-cols-1 md:grid-cols-2 gap-12">
<ProductImages product={product} cartProduct={CartProduct} handleColourSelect={handleColorSelect}/>
<div className="flex flex-col gap-1"><h2 className="text-2xl">{product.name}</h2>
<div className="flex gap-2">
<Rating value={ProductRating} readOnly/>
<div className="flex gap-2">{product.reviews.length} rewiews</div>
</div>
<Horizontal/>
<div className=" text-justify">{product.description}</div>
<Horizontal/>
<div>
<span className="font-semibold">Category: </span>{product.category}
</div>
<div>
<span className="font-semibold">Brand: </span>{product.brand}
</div>
<div className={product.inStock ?' text-teal-400':' text-red-400'}>{product.inStock ?'In Stock':'Out of Stock'}</div>
<Horizontal/>
{isProductinCart?
<>
<p className="mb-2 text-slate-500 flex items-center gap-2">
<BsFillCheckCircleFill size={20} className="text-teal-400" />
<span>Product added to Cart</span>
</p>
<div className=" max-w-[300px]">
<Button label="View Cart" outline onClick={()=>{router.push('/cart')}}/>
</div>
</>:
<>
<SetColor cartProduct={CartProduct} images={product.images} handleColorSelect={handleColorSelect}/>
<Horizontal/>
<SetQuantity cartProduct={CartProduct} handleQuantityDec={handleQuantityDec} handleQuantityInc={handleQuantityInc} />
<Horizontal/>
<div className=" max-w-[300px]">
<Button label="Add to cart" onClick={()=>handleAddProductCart(CartProduct)}/>
</div>
</>}
</div>
</div>
);
}
export default ProductDetails;
这是产品详细信息页面,当我点击产品卡时会显示 https://github.com/briankaine1604/bloomy.git 链接到包含代码(如果需要)的 github 存储库
您遇到的问题是由于产品 ID 及其接口 IParams 的动态路由的命名约定存在错误。您将产品 ID 的文件夹命名为 productid,并带有小写“i”,但在界面 IParams 中,您传递的是带有大写“I”的 productId。您需要对文件夹及其接口 IParams 使用相同的命名约定。您可以使用 productid 或 productId。