I am working on a react project and trying to show more details on a product with react-router
useParams
, but I keep getting the error 'Cannot destructure property 'title' of 'product' as it is undefined
.
Here's the code for the single products
import React from "react";
import products from "../data2";
import { Link, useParams } from "react-router-dom";
const SingleProducts = () => {
const { productId } = useParams();
const product = products.find((productg) => productg.id === productId);
const { title } = product;
return (
<section className="section product">
<img />
<h3>{title}</h3>
<h3></h3>
<Link to="/products">Back home</Link>
</section>
);
};
export default SingleProducts;
and here's for the product items
import React from 'react'
import { products } from '../data2'
import style from '../Styles/ProductItem.module.scss'
import StarRateIcon from '@mui/icons-material/StarRate';
import {Link} from "react-router-dom"
const ProductItem = () => {
return (
<div className={style.container}>
{products.map((item)=>{
return (
<article key={item.id} className={style.product}>
<h1>{item.title}</h1>
<h1>{item.id}</h1>
<div>
<img src={item.images} />
</div>
<div>
<p>{item.title}</p>
<h4>${item.price}</h4>
<p>{item.stock} items left</p>
<div className={style.rating}>
<p>{item.rating}</p>
<StarRateIcon className={style.star}/>
</div>
</div>
<Link to={`/products/${item.id}`}><button className={style.btn}>View more</button></Link>
<div className={style.discount}>
<p>- {item.discountPercentage} %</p>
</div>
</article>);
})}
</div>
)
}
export default ProductItem
CodePudding user response:
Array.prototype.find
potentially returns undefined
if no match is found. The component logic should handle this case and only attempt to access into defined objects. Add a check on the returned product
value and conditionally render alternative UI.
You should also be aware that the route path params will always be a string type, so you'll want to ensure you are using a type-safe comparison in the find
predicate function. Converting the value you are comparing against the path param to a string is sufficient.
Example:
const SingleProducts = () => {
const { productId } = useParams();
const product = products.find((productg) => String(productg.id) === productId);
if (!product) {
return "No matching product found.";
}
const { title } = product;
return (
<section className="section product">
<img />
<h3>{title}</h3>
<h3></h3>
<Link to="/products">Back home</Link>
</section>
);
};