I am working on an E-commerce website and adding a 'cart' route on it, but it got the following Error: Error image The localhost address is :3000/cart, but the error address is from :3000/api/products/cart.(I am using express to fetch data from :http://localhost:5000/api/products)
Also, if I input the address as:" http://localhost:3000/cart/223", the error came out as:
GET http://localhost:3000/cart/api/products/cart 404 (Not Found)
App.js :
function App() {
return (
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/products" component={ProductPage}/ >
<Route path="/:id" component={ProductDetail} />
<Route path="/cart" component={CartPage} />
<Route path="/cart/:id" component={CartPage} />
</Switch>
)
}
export default App;
cartPage.jsx :
import React, { useEffect } from "react";
import { addToCart } from "../actions/cartActions";
import { useDispatch } from "react-redux";
function CartPage(props) {
const productId = props.match.params.id;
const qty = props.location.search? Number(props.location.search.split("=")[1]): 1;
const dispatch = useDispatch();
useEffect(() => {
if (productId) {
dispatch(addToCart(productId, qty));
}
}, []);
return <div>Hell world!</div>;
}
export default CartPage;
productDetail.jsx:
import React, { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { detailsProduct } from "../actions/productActions";
function ProductDetail(props) {
const [qty, setQty] = useState(1);
const productDetails = useSelector((state) => state.productDetails);
const { product, loading, error } = productDetails;
const dispatch = useDispatch();
useEffect(() => {
dispatch(detailsProduct(props.match.params.id));
return () => {//};
}, []);
const handleAddToCart = () => {
props.history.push("/cart/" props.match.params.id "?qty=" qty);
};
return ({product.countInStock > 0 && (
<button onClick={handleAddToCart}>
Add to Cart
</button>
)})
http://localhost:5000/api/products
:
[
{
name: "Slim Shirt",
category: "Shirts",
image: "/img/d2.png",
price: 60,
brand: "Nike",
rating: 4.5,
numReviews: 10,
_id: "123",
countInStock: 0,
},
{
name: "Best Shirt",
category: "Shirts",
image: "/img/d3.png",
price: 50,
brand: "ads",
rating: 4.6,
numReviews: 12,
_id: "223",
countInStock: 6,
},
....}
server.js:
import express from "express";
import { data } from "./data";
const app = express();
app.get("/api/products/:id", (req, res) => {
const product = data.find((x) => x._id === req.params.id);
if (product) {
res.send(product);
} else {
res.status(404).send({ msg: "Product Not Found!!" });
}
});
app.get("/api/products", (req, res) => {
res.send(data);
});
app.listen(5000, () => {
console.log("server started at http://localhost:5000");
});
package.jason:
{
"name": "frontend",
"proxy": "http://127.0.0.1:5000",
"version": "0.1.0",
"private": true,
"dependencies": {
.....}
CodePudding user response:
Try moving your cart routes above your /:id route.
CodePudding user response:
Issue
The issue seems to start with the order of the routes rendered by the Switch
component. Route path order and specificity matters within the Switch
. The "/:id"
route path is less specific than "/cart"
which is less specific than "/cart/:id"
, and so it will be matched and rendered by the Switch
.
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/products" component={ProductPage} />
<Route path="/:id" component={ProductDetail} /> // matches "/cart"
<Route path="/cart" component={CartPage} /> // unreachable route!!
<Route path="/cart/:id" component={CartPage} /> // unreachable route!!
</Switch>
The last two routes are unreachable. The wrong component is rendered when the path is "/cart"
and an invalid request is made.
ProductDetail dispatches an action that is likely meant to make a fetch request with a proper id, bu "cart"
is the id
value with path "/cart"
matched by the "/:id"
route.
useEffect(() => {
dispatch(detailsProduct(props.match.params.id));
return () => {};
}, []);
Solution
Reorder the routes in inverse order of path specificity. In most cases doing this also completely removes the need to pepper all the routes with the exact
prop.
Example:
<Switch>
<Route path="/cart/:id" component={CartPage} />
<Route path="/cart" component={CartPage} />
<Route path="/products" component={ProductPage} />
<Route path="/:id" component={ProductDetail} />
<Route path="/" component={HomePage} />
</Switch>
Note that "/cart/:id"
is more specific than "/cart"
, "/products"
, and "/:id"
, and that both "/cart"
and "/products"
are more specific than "/:id"
, and they are all more specific than the last route path "/"
.
Note also that react-router-dom@5
allows the Route
component to use an array of paths for the path
prop. Keep in mind that the order and specificity still matters within the array. Keep also in mind that all routes in the array should be more specific than the paths of routes below/after.
Example:
<Switch>
<Route path={["/cart/:id", "/cart"]} component={CartPage} />
<Route path="/products" component={ProductPage} />
<Route path="/:id" component={ProductDetail} />
<Route path="/" component={HomePage} />
</Switch>