How to properly do a dynamic route in reactJs when working with Add to Cart ecommerce functionality

Viewed 580

I'm making a e-commerce. For the add to cart, i defined an addToCartHandler as follows:

let params = useParams();
  let navigate = useNavigate();
  const dispatch = useDispatch();
  const productId = params.id;
  const [qty, setQty] = useState(1);
  const productDetails = useSelector((state) => state.productDetails);
  const { loading, error, product } = productDetails;

  useEffect(() => {
    dispatch(detailsProduct(productId));
  }, [dispatch, productId]);

  const addToCartHandler = () => {
    navigate(`/cart/${productId}?qty=${qty}`);
  };
  

The URL renders correctly dan dynamically according to the productId and qty of the added to cart product

Screenshot of the URL whenever the add to cart button is clicked

enter image description here

But the cartscreen is empty even though the URL renders as expected. Here is the CartScreen code. Did it suppose to locate the quantity at the end of the URL after the? sign. Example URL: "/cart/2?qty=15". So I use useLocation() and search.split("=")2

import React from "react";
import { useParams, useLocation } from "react-router-dom";

export default function CartScreen(props) {
  let params = useParams();
  let location = useLocation();
  const productId = params.id;
  const qty = location.search ? Number(location.search.split("=")[1]) : 1;

  return (
    <div>
      <h1>Cart Screen</h1>
      <p>
        ADD TO CART : ProductID: {productId} Qty: {qty}
      </p>
    </div>
  );
}

It returns an empty cart screen with the following error in the console:

No routes matched location "/cart/2?qty=15"

I guess it's because the route in App.js. But I'm not sure. My routes are as follows:

 <Route path="/cart/:id?" element={<CartScreen />}></Route>

I'm actually following this video tutorial: https://www.youtube.com/watch?v=TRCDsB9i3bI&t=9077s and the error I got is when I do the section 02:57:24 Part 14- Handle Add To Cart Button.

It might also have to do with the different react-router versions?

Here are my versions:

  "axios": "^0.24.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-redux": "^7.2.6",
    "react-router": "^6.0.0",
    "react-router-dom": "^5.2.0",
    "react-scripts": "4.0.3",
    "redux": "^4.1.2",
    "redux-thunk": "^2.4.0",
    "web-vitals": "^1.0.1",
    "with-router": "^1.0.1"

And the versions of the tutorial are:

"axios": "^0.20.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-google-charts": "^3.0.15",
"react-paypal-button-v2": "^2.6.2",
"react-redux": "^7.2.1",
"react-responsive-carousel": "^3.2.10",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.3",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"socket.io-client": "^4.0.1"

What should I do?

3 Answers

Instead of this

<Route path="/cart/:id?" element={<CartScreen />}></Route>

Use this:

<Route path="/cart/:id" element={<CartScreen />}></Route>

Just remove ? from path, if it doesn't work use this code for CartScreen:

   const CartScreen = () => {
   const { id } = useParams();
   const productId = id;
   console.log("ID :", productId);
   const { search } = useLocation();
   const qtyInUrl = new URLSearchParams(search).get("qty");
   console.log("QTY", qtyInUrl);
   const qty = qtyInUrl ? Number(qtyInUrl) : 1;
   const dispatch = useDispatch();
   useEffect(() => {
   if (productId) {
    dispatch(addToCart(productId));
    }
   }, [dispatch, productId]);

  return (
   <div>
    <h1>Cart Screen</h1>
    <p>
       Add to Cart : Product ID : {productId} QTY: {qty}
    </p>
  </div>
 );
};

<Route path="/cart/:id?" element={<CartScreen />}>

try to change to that and see if it works in your case:

<Route path="/cart/:id/*" element={<CartScreen />}>

import React from 'react';
import { useParams } from 'react-router-dom';

export const CartScreen = () => {
    const qty = window.location.search?window.location.search.split("=")[1]:1
    const {id} =  useParams()
    const productId = id
  return (
  <div>
      <h1>Cart Screen</h1>
      <p>
          ADD TO CART : ProductID: {productId} Qty: {qty}
      </p>
  </div>
  );
};

Route code should look like this:

<Route path="/cart/:id/*" element={<CartScreen />}>
Related