Reputation: 119
I have a product page, where if the user clicks on a specific product card, it will redirect the user to a new page where that specific product details will be displayed only. However, in my code, even after redirecting it to the details page, it still shows the entire product list on that page. I need a bit of help to solve this issue. I have tried passing props to differentiate. But it doesn't seem to work. My FeaturedProduct.js:
import React from "react";
import { useState, useEffect } from "react";
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import ProductDetails from "./ProductDetails";
import axios from "axios";
function FeaturedProduct(props) {
const [products, setProducts] = useState([]);
useEffect(() => {
fetchProducts();
}, []);
function fetchProducts() {
axios
.get("https://shoppingapiacme.herokuapp.com/shopping")
.then((res) => {
console.log(res);
setProducts(res.data);
})
.catch((err) => {
console.log(err);
});
}
return (
<div>
<h1> Your Products List is shown below:</h1>
<div className="item-container">
{products.map((product) => (
<div className="card" key={product.id}>
{" "}
<h3>{product.item}</h3>
<p>
{product.city}, {product.state}
</p>
<Router>
<Link to="/productdetails">More Details</Link>
<Switch>
<Route path="/productdetails">
<ProductDetails product={product}/>
</Route>
</Switch>
</Router>
</div>
))}
</div>
</div>
);
}
export default FeaturedProduct;
My ProductDetails.js:
function ProductDetails(props) {
const {name, color} = props.product;
return (
<div>
<div>
<h1>{name}</h1>
<h1>{color}</h1>
</div>
</div>
);
}
export default ProductDetails;
My App.js:
import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import FeaturedProduct from "./FeaturedProduct";
import "./App.css";
function App() {
return (
<div className="App">
<FeaturedProduct />
</div>
);
}
export default App;
Upvotes: 3
Views: 10984
Reputation: 203208
You are rendering that same router/link/route for each mapped product element.
<Router>
<Link to="/productdetails">More Details</Link>
<Switch>
<Route path="/productdetails">
<ProductDetails product={product}/>
</Route>
</Switch>
</Router>
This means when the path is "/productdetails" you render a Route
and ProductDetails
component for each and every one of them.
It is more common to render one single Router
and Route
for a product details page with either a specific product id
as a route param or to pass entire product object in route state (though less common).
Move the Router
into App
to provide a single routing context to the app:
function App() {
return (
<Router>
<div className="App">
<FeaturedProduct />
</div>
</Router>
);
}
Move the Switch
and Route
below the products
mapping, leaving only the Link
in the map callback. Link to a specific product id
and use the Route
's render
prop to search for the matching product by id
to pass in as a prop:
function FeaturedProduct(props) {
const [products, setProducts] = useState([]);
useEffect(() => {
fetchProducts();
}, []);
function fetchProducts() {
axios
.get("https://shoppingapiacme.herokuapp.com/shopping")
.then((res) => {
console.log(res);
setProducts(res.data);
})
.catch((err) => {
console.log(err);
});
}
return (
<div>
<h1> Your Products List is shown below:</h1>
<div className="item-container">
{products.map((product) => (
<div className="card" key={product.id}>
<h3>{product.item}</h3>
<p>
{product.city}, {product.state}
</p>
<Link to={`/product/${product.id}`}>More Details</Link>
</div>
))}
</div>
<Switch>
<Route
path="/product/:id"
render={({ match }) => (
<ProductDetails
product={products.find(
(product) => String(product.id) === match.params.id
)}
/>
)}
/>
</Switch>
</div>
);
}
Upvotes: 1