this my single product page
import React from "react";
import { Link } from "react-router-dom";
import Rating from "../components/Rating";
import Product from "../Data";
import { Row, Button, Col, Image, ListGroup, Card } from "react-bootstrap";
// import PropTypes from 'prop-types';*
This where I tired to find the match id and render the product with match id
const Products = ({match}) => {
const product = Product.find((p) => p._id === match.params.id);
return (
<>
<Link className="btn btn-dark my-3" to="/" />
Go Back
<Row>
<Col md={6}>
<Image src={product.img} fluid />
</Col>
<Col md={3}>
<ListGroup variant="flush">
<ListGroup.Item>
<h3>{product.name}</h3>
</ListGroup.Item>
</ListGroup>
<ListGroup.Item>
<Rating
value={product.Rating}
text={`${product.numReviews}`}
/>
</ListGroup.Item>
<ListGroup.Item>
<p>Description:{product.desc}</p>
</ListGroup.Item>
<ListGroup.Item>
<p>price: $ {product.price}</p>
</ListGroup.Item>
</Col>
<Col md={3}>
<Card>
<ListGroup variant="flush">
<ListGroup.Item>
<Row>
<Col>Price:</Col>
<Col>
<strong>$ {product.price}</strong>
</Col>
</Row>
</ListGroup.Item>
<ListGroup.Item>
<Row>
<Col>Status:</Col>
<Col>
{product.countInStock > 0 ? "In Stock" : "Out Of Stock"}
</Col>
</Row>
</ListGroup.Item>
<ListGroup.Item>
<Button
className="btn btn-primary"
type="button"
disabled={product.countInStock === 0}
>
Add To Cart
</Button>
</ListGroup.Item>
</ListGroup>
</Card>
</Col>
</Row>
</>
);
};
export default Products;
This is my single product screen
import Products from "./pages/Products";
const App = () => {
return (
<BrowserRouter>
<Header />
<main className="py-3">
<Container>
<Routes>
<Route index element={<Home />} />
<Route path="product" element={<Products />} />
<Route path=":id" element={<Products />} />
</Routes>
</Container>
</main>
<Footer />
</BrowserRouter>
);
};
export default App;
Try this:
<Routes>
<Route path="/" element={<Home />} />
<Route path="product/:id" element={<Products />} />
</Routes>
Your product page:
const {id} = useParam() // we can destructure out the id
const fetchProduct = async (id) => {
const resultFromServer = await fetch(`url/${id}`)
const dataFromServer = await resultFromServer.json()
// with the data, now we can store it in useState or Context api
// depends on your implementation, and show it to the client
}
useEffect(() => {
if(id) fetchProduct(id) // Fetch product based on url id
},[]);
In react-router-dom v6 the Route
components no longer have route props ( history
, location
, and match
), and the current solution is to use the React hooks "versions" of these to use within the components being rendered.
In other words, props.match
is undefined. This should also be clear since no props are passed to Products
.
<Route path=":id" element={<Products />} /> // <-- no props passed to Products
Use the useParams
hook to access the id
route path param in the Products
component. Don't forget that Array.prototype.find
can potentially return undefined if no element matches the predicate, so your UI code should handle this case. ( avoids "undefined access of X" exceptions )
Example:
import { Link, useParams } from 'react-router-dom';
const Products = () => {
const { id } = useParams();
const product = Product.find((p) => p._id === id);
if (!product) return "No matching product found.";
return (
<>
...
</>
);
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.