-1

Goal: I should transfer all the added product items from the product cart to the payment page after the user will click the checkout button.

Product items inside the product cart: product items

I should transfer the product items here in the Payment page (after checkout button is clicked):

payment page

Problem: I am not sure how to transfer the product items(including its prices, total prices, and increment/decrement buttons) to the payment page, even by using props and replicating mapping functionality of the Basket.jsx(where the cart functionality is found).

I know I shouldn't be replicating the functionality, especially in terms with mapping since there would be one and only one parent component for this.

Source code for Basket.jsx:

import React from "react";
import {
  BrowserRouter as Router,
  Routes,
  Route,
  useNavigate
} from "react-router-dom";

export default function Basket(props) {
  const navigate = useNavigate();

  const navigateToPaymentPage = () => {
    navigate("/paymentpage");
  };

  const { cartItems, onAdd, onRemove } = props;

  const itemsPrice = cartItems.reduce((a, c) => a + c.price * c.qty, 0);

  const totalPrice = itemsPrice;
  // const totalPrice = itemsPrice + discountItemPrice ---- for discount items soon

  return (
    <aside className="block col-1">
      <h2>Cart Items</h2>

      {/* Display message when cartItemsLength is 0 */}
      <div>{cartItems.length === 0 && <div>Cart is Empty</div>} </div>

      {/* Renders the added item to the basket of the shopping cart through mapping cartItems */}
      {cartItems.map((item) => (
        <div key={item.id} className="row">
          <div className="col-2">
            {item.name} -- ${item.price.toFixed(2)}
          </div>

          {/* Increment and Decrement Buttons */}
          <div className="col-2">
            <button onClick={() => onRemove(item)} className="remove">
              -
            </button>
            <button onClick={() => onAdd(item)} className="add">
              +
            </button>
            Qty: {item.qty}
          </div>

          <div className="col-2 text-right">
            ${(item.price * item.qty).toFixed(2)}
          </div>
        </div>
      ))}

      {cartItems.length !== 0 && (
        <>
          <hr></hr>

          <div className="row">
            <div className="col-2">
              <strong>Total Price</strong>
            </div>
            <div className="col-1 text-right">
              <strong>${totalPrice.toFixed(2)}</strong>
            </div>
          </div>
          <hr />
          <div className="row">
            <button onClick={navigateToPaymentPage}>Checkout</button>
          </div>
        </>
      )}
    </aside>
  );
}

Source code for PaymentPage.jsx:

import React from "react";
import {
  BrowserRouter as Router,
  Routes,
  Route,
  useNavigate
} from "react-router-dom";

export default function PaymentPage(props) {

    //I replicated the functionality here:
  const { cartItems, onAdd, onRemove } = props;

  const itemsPrice = cartItems.reduce((a, c) => a + c.price * c.qty, 0);

  const totalPrice = itemsPrice;

  const navigate = useNavigate();

  const navigateToHomeOrderPage = () => {
    navigate("/");
  };

  return (
    <aside className="block col-1">
      <button
        sx={{ width: 10 }}
        style={{ maxWidth: "60px" }}
        onClick={navigateToHomeOrderPage}
      >
        Go back
      </button>
      <h2>PAYMENT PAGE</h2>

      {/* Display message when cartItemsLength is 0 */}
      <div>{cartItems.length === 0 && <div>Cart is Empty</div>} </div>

      {/* Renders the added item to the basket of the shopping cart through mapping cartItems */}
      {cartItems.map((item) => (
        <div key={item.id} className="row">
          <div className="col-2">
            {item.name} -- ${item.price.toFixed(2)}
          </div>

          {/* Increment and Decrement Buttons */}
          <div className="col-2">
            <button onClick={() => onRemove(item)} className="remove">
              -
            </button>
            <button onClick={() => onAdd(item)} className="add">
              +
            </button>
            Qty: {item.qty}
          </div>

        
          <div className="col-2 text-right">
            ${(item.price * item.qty).toFixed(2)}
          </div>
        </div>
      ))}

      {cartItems.length !== 0 && (
        <>
          <hr></hr>

          <div className="row">
            <div className="col-2">
              <strong>Total Price</strong>
            </div>
            <div className="col-1 text-right">
              <strong>${totalPrice.toFixed(2)}</strong>
            </div>
          </div>
          <hr />
        </>
      )}
    </aside>
  );
}

Full source codes (functioning App):

https://codesandbox.io/s/productitemsdisplayfixing-cherry-h0br4o-forked-nvu3d0?file=/src/components/PaymentPage.jsx:0-1954

Code Basis: https://www.youtube.com/watch?v=AmIdY1Eb8tY&t=2209s

Your responses would indeed help and guide me a lot since I am very much confused on how to pass these data from one page component to another. Thus, it would be great to hear guides and responses from all of you. Thank you very much!

Ralph Henry
  • 122
  • 1
  • 13
  • Did you just delete and repost the same [question](https://stackoverflow.com/questions/73845375/how-to-transfer-product-items-from-the-product-cart-to-the-payment-page-after-cl)? Are there any new details? Where is the code trying to send any data from one page to another? – Drew Reese Sep 26 '22 at 07:52
  • Yes, clearly I deleted the old question since it might be too complex. Thus, here we are with a fresh and simplified question since no one even bothered to respond. – Ralph Henry Sep 26 '22 at 08:08
  • As you can see from the question details above, I want to send the product items (coming from the product cart) to the payment page after I have clicked the checkout button – Ralph Henry Sep 26 '22 at 08:09
  • So the code does `navigate("/paymentpage");`. Are you wanting/trying to pass some state in the route transition? – Drew Reese Sep 26 '22 at 08:10
  • Yes, exactly, I want to pass the product items into the payment page using that route – Ralph Henry Sep 26 '22 at 08:13
  • 1
    Does this help answer your question? https://stackoverflow.com/a/59701168/8690857 Or more specifically to the `navigate` function, https://stackoverflow.com/a/69714441/8690857? – Drew Reese Sep 26 '22 at 08:14
  • Ohh nice, it involves routers and navigation to pass data. Some of the answers contain your responses. Will look upon this one and give out any updates after I have implemented it. – Ralph Henry Sep 26 '22 at 08:23
  • Update, as of this moment, the product items still does not display even after following the navigate functionality. I am quite confused on the part on how to access the object's values and display them on another page. – Ralph Henry Sep 28 '22 at 17:35
  • Ralph, would it be possible to create a *running* [codesandbox](https://codesandbox.io/) of your latest attempt at this? Or has the sandbox in your question been updated? The one you initially provided too much of a rewrite and it wasn't clear what exactly you were trying to pass from where to where. – Drew Reese Sep 28 '22 at 20:46

1 Answers1

2

Just as in the linked answer in the comments, you can pass the data in the state option of the navigate function

  const navigate = useNavigate();
  const { cartItems, onAdd, onRemove } = props;
  const itemsPrice = cartItems.reduce((a, c) => a + c.price * c.qty, 0);
  const totalPrice = itemsPrice;
  const navigateToPaymentPage = () => {
    navigate("/paymentpage", {
      state: {
        totalPrice,
        cartItems
      }
    });
  };

And then get it on the other page from the location object

  const navigate = useNavigate();
  const location = useLocation();
  const navigateToHomeOrderPage = () => {
    navigate("/");
  };
  const data = location.state;
  return (
    <aside className="block col-1">
      <button
        sx={{ width: 10 }}
        style={{ maxWidth: "60px" }}
        onClick={navigateToHomeOrderPage}
      >
        Go back
      </button>
      <h2>PAYMENT PAGE</h2>
      {JSON.stringify(data)}
    </aside>
  );

You can check the updated sandbox https://codesandbox.io/s/react-router-dom-pass-state-r1iis7?file=/src/components/Basket.jsx

However, a cart implementation usually uses a backend as a source of truth, but if your project is for learning purposes, I recommend you to also take a look at global state management libraries, the most common is reduxjs in case you need to persist the data through route changes or even between page reloads if you add redux-persist

diedu
  • 19,277
  • 4
  • 32
  • 49
  • Hello @diedu, your code tweaks in terms of my code issue indeed really worked. What I was really confused on my end before is in terms of how I can utilize the passed data inside the receiving page component(PaymentPage), in terms of const { state } = useLocation(); . Now, since you have intialized const data = location.state; , this is now the vital part of accessing and displaying the data. This is literally the piece that was missing in terms of getting the data. Thus your explanation and presentation made it very very clear and straight to the point. – Ralph Henry Sep 29 '22 at 10:25
  • This mini cart implementation was just created in order to get the clear and full logic in terms of using and passing the data. Clearly, the data used here is initialized manually, but on our main full project system, we used Spring for the backend and Docker for running the full project system in terms of its API. – Ralph Henry Sep 29 '22 at 10:35