'React js: fail to get specific product data when clicking on one product
The code below fail to get specific data when clicking on a product: In Product.js:
<Link to={`/product/${item.id}`}>
<p className='product_title'>{item.title}</p>
</Link>
In App.js
<Route path='/product/:id'>
<Header />
<DetailProductPage />
</Route>
All the above seem work well, but the DetailProductPage has problems. code shown as below. The code successfully get {id} = useParams(), but the code fails to get the details. The code within the useEffect() does not work, and "fail to load" the data.
import React, { useEffect, useState } from 'react';
import { Col, Row } from 'antd';
import ProductImages from './ProductImages';
import ProductInfo from './ProductInfo';
import {productItems} from '../Data';
import { useParams } from 'react-router-dom';
function DetailProductPage() {
const { id }=useParams();
const [details, setDetails]=useState([])
useEffect(() => {
productItems.map((item) =>
{
if (item.id === id) {
return (setDetails(item))
} else { console.log("fail to load")}
})
}, [id]);
return (
<div className="postPage" style={{width:'100%', padding: '3rem 4rem'}}>
<div style={{display: 'flex', justifyContent:'center'}}>
<h1>ID: {details.id}</h1>
</div>
</div>
)
}
export default DetailProductPage
Solution 1:[1]
The common source of error with useParams is that everything is a string. If you want to make comparisons, you will have to cast it to the same type or use == for the comparison.
First Approach - Cast it to the same type
function DetailProductPage() {
// id is a string
const { id }=useParams();
const [details, setDetails]=useState([])
useEffect(() => {
// Using find as it makes a nicer syntax
setDetails(productItems.find(item => String(item.id) === id))
// Or setDetails(productItems.find(item => item.id === Number(id)))
}, [id]);
return (
<div className="postPage" style={{width:'100%', padding: '3rem 4rem'}}>
<div style={{display: 'flex', justifyContent:'center'}}>
<h1>ID: {details.id}</h1>
</div>
</div>
)
}
Read more about find here
Second Approach - use ==
function DetailProductPage() {
const { id }=useParams();
const [details, setDetails]=useState([])
useEffect(() => {
setDetails(productItems.find(item => item.id == id))
}, [id]);
return (
<div className="postPage" style={{width:'100%', padding: '3rem 4rem'}}>
<div style={{display: 'flex', justifyContent:'center'}}>
<h1>ID: {details.id}</h1>
</div>
</div>
)
}
If the above approaches doesn't work for you here is a working example. This is using router-router-dom version 6.
import { BrowserRouter, Route, Routes, useParams } from "react-router-dom";
import { useEffect, useState } from "react";
const products = [
{ id: 1, content: "Hello 1" },
{ id: 2, content: "Hello 2" },
{ id: 3, content: "Hello 3" }
];
export const Details = () => {
const { id } = useParams();
const [product, setProduct] = useState();
useEffect(() => {
setProduct(products.find((item) => item.id === Number(id)));
}, [id]);
return <pre>{JSON.stringify(product, null, 2)}</pre>;
};
export default function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/product/:id" element={<Details />} />
</Routes>
</BrowserRouter>
);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | kwaku hubert |
