I am working on a small car e-shop project. I am trying to get the ProductDetails
rendering in a new page when the user clicks on "more details" in Products
, however, it is failing. First it is not showing the path at the browser bar which should be "http://localhost:3000/product-details"
and second it is rendering the Home
page.
App.js
import React from 'react';
import Cart from './pages/Cart';
import Home from './pages/Home';
import ProductDetails from './pages/ProductDetails';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import { Navigate } from 'react-router-dom';
function App() {
return (
<Router>
<Routes>
<Route>
<Route path="/home" element={<Home />} />
<Route path="/cart" element={<Cart />} />
<Route path="/product-details/:id" element={<ProductDetails />} />
<Route path="*" element={<Navigate to ="/home" replace />} />
</Route>
</Routes>
</Router>
);
}
export default App;
Products.js
import React from 'react';
import toyota from '../assets/images/toyota_camry2023.png'
import honda from '../assets/images/honda_civic2023.png';
import ford from '../assets/images/ford_mustang2023.png';
import { Link } from 'react-router-dom';
function Products() {
const cars = [
{ id: 1, name: 'Toyota Camry', price: 25000, img: toyota },
{ id: 2, name: 'Honda Civic', price: 27000, img: honda },
{ id: 3, name: 'Ford Mustang', price: 35000, img: ford },
]
return (
<div>
<h2>Find The Best Deals</h2>
<h2>Available Cars</h2>
<ul>
{cars.map(car => (
<li key={car.id}>
<img src={car.img} alt={car.name} />
<h3>{car.name}</h3>
<p>Price: ${car.price}</p>
<Link to={`product-details/${car.id}`} target="_blank">More details</Link>
</li>
))}
</ul>
</div>
)
}
export default Products;
ProductDetails.js
import React from 'react';
import { useParams } from 'react-router-dom';
function ProductDetails() {
const { id } = useParams();
const Product = {
1: {
Engine: '2.5L Inline-4 Gas',
Drivetrain: 'Front-Wheel Drive',
Transmission: '8-Speed Automatic',
Warranty: '5 Years / 100000 km'
},
2: {
Engine: 'Turbocharged DOHC 16-valve Inline-4',
Drivetrain: 'Front-Wheel-Drive,',
Transmission: 'Continuously Variable Automatic',
Warranty: '3 Years / 60000 km'
},
3: {
Engine: 'Intercooled Turbo Premium Unleaded I-4',
Drivetrain: 'Rear Wheel Drive with limited-slip differential',
Transmission: '10-speed automatic transmission',
Warranty: '3 years / 60000 km'
},
};
const ProductDetails = Product[id];
return (
<div>
<h2>Car Details</h2>
<p>{ProductDetails.Engine}</p>
<p>{ProductDetails.Drivetrain}</p>
<p>{ProductDetails.Transmission}</p>
<p>{ProductDetails.Warranty}</p>
<button>Add to Cart</button>
<button>Book a Test Drive</button>
</div>
)
}
export default ProductDetails;
Would you be able to help me sort this issue out. I tried changing the routing, checked the syntax, followed my tutorials, all with no success.
The Product
component is rendered by the Home
component rendered on route path "/home"
and uses relative link target paths. Relative paths work relative to the current URL path. When the current URL path is "/home"
and a link target is to={`product-details/${car.id}`}
, then the resulting navigation action will be to "/home/product-details/someIdValue"
. Since there is no explicit route path that matches the URL path, the path="*"
wildcard matcher/"catch all" route is rendered and the UI redirects to "/home"
.
Use absolute link target paths. The difference between relative and absolute routes paths is that absolute paths start from root, e.g. "/"
. In other words, add a leading "/"
character to your link target path values.
Example:
to={`/product-details/${car.id}`}
Code:
const cars = [
{ id: 1, name: 'Toyota Camry', price: 25000, img: toyota },
{ id: 2, name: 'Honda Civic', price: 27000, img: honda },
{ id: 3, name: 'Ford Mustang', price: 35000, img: ford },
]
function Products() {
return (
<div>
<h2>Find The Best Deals</h2>
<h2>Available Cars</h2>
<ul>
{cars.map(car => (
<li key={car.id}>
<img src={car.img} alt={car.name} />
<h3>{car.name}</h3>
<p>Price: ${car.price}</p>
<Link to={`/product-details/${car.id}`}>
More details
</Link>
</li>
))}
</ul>
</div>
);
}