How to Build a Shopping Cart with React and Stripe

In this tutorial, we will learn how to build a shopping cart using React and integrate Stripe for payment processing. The shopping cart will allow users to add items to their cart, update quantities, and remove items. When the user is ready to checkout, they will be redirected to the Stripe payment page to complete the purchase.

Before we begin, make sure you have Node.js and npm installed on your machine. You will also need a Stripe account to obtain the necessary API keys.

1. Setting up the Project

Let’s start by setting up a new React project.

Open a terminal and run the following command:

npx create-react-app shopping-cart

Once the project is created, navigate to the project directory:

cd shopping-cart

2. Installing Dependencies

Next, we need to install the necessary dependencies for our project. We will use the stripe and react-stripe-checkout libraries for integrating Stripe payment processing.

Run the following command to install the dependencies:

npm install stripe react-stripe-checkout

3. Setting up Stripe

To integrate Stripe into our shopping cart, we need to obtain the necessary API keys.

  1. Log in to your Stripe account, or create a new account if you don’t have one.
  2. In the Dashboard, navigate to Developers > API keys.
  3. Copy your Publishable key and Secret key. We will use these in our code.

4. Creating the Shopping Cart Component

Now let’s start building our shopping cart component.

Create a new file called ShoppingCart.js in the src directory and add the following code:

import React, { useState } from 'react';

const ShoppingCart = () => {
  const [cartItems, setCartItems] = useState([]);

  // TODO: Implement add to cart, update quantity, remove item, and checkout functions

  return (
    <div>
      {/* TODO: Display cart items */}
      {/* TODO: Implement add to cart, update quantity, and remove item buttons */}
      {/* TODO: Implement checkout button */}
    </div>
  );
};

export default ShoppingCart;

In the code above, we import the useState hook from React to manage the cart items state. We also define the cartItems state variable as an empty array. We will use this array to store the items in the cart.

5. Displaying Cart Items

Let’s start by displaying the items in the cart.

Update the ShoppingCart component code as follows:

import React, { useState } from 'react';

const ShoppingCart = () => {
  const [cartItems, setCartItems] = useState([]);

  return (
    <div>
      <h2>Shopping Cart</h2>
      {cartItems.length === 0 ? (
        <p>No items in cart</p>
      ) : (
        <ul>
          {cartItems.map((item, index) => (
            <li key={index}>
              {item.name} - {item.quantity}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
};

export default ShoppingCart;

In the updated code, we display a heading “Shopping Cart” and check if cartItems.length is zero. If the length is zero, we display a message “No items in cart”. Otherwise, we map through the cartItems array and display each item name and quantity as a list item.

6. Adding Items to Cart

Let’s implement the functionality to add items to the cart.

Update the ShoppingCart component code as follows:

import React, { useState } from 'react';

const ShoppingCart = () => {
  const [cartItems, setCartItems] = useState([]);

  const addToCart = (item) => {
    const existingItem = cartItems.find((i) => i.id === item.id);
    if (existingItem) {
      setCartItems(
        cartItems.map((i) =>
          i.id === item.id ? { ...i, quantity: i.quantity + 1 } : i
        )
      );
    } else {
      setCartItems([...cartItems, { ...item, quantity: 1 }]);
    }
  };

  return (
    <div>
      {/* Display cart items */}
      {/* Implement add to cart, update quantity, and remove item buttons */}
      {/* Implement checkout button */}
    </div>
  );
};

export default ShoppingCart;

In the updated code, we define the addToCart function. This function takes an item as a parameter and checks if the item already exists in the cart (existingItem). If it exists, we update the quantity of the item by finding it in the cartItems array with find, and if not, we add the item to the array with a quantity of 1 ([...cartItems, { ...item, quantity: 1 }]). Finally, we update the cartItems state with setCartItems.

To test the functionality, update the code where you’re rendering the ShoppingCart component:

import React from 'react';
import ShoppingCart from './ShoppingCart';

const App = () => {
  const item = {
    id: 1,
    name: 'Example Item',
  };

  return (
    <div>
      <h1>Shopping App</h1>
      <ShoppingCart />
      <button onClick={() => addToCart(item)}>Add to cart</button>
    </div>
  );
};

export default App;

In the code above, we define an item object and pass it as a prop to the ShoppingCart component. We also add a button and an onClick event that calls the addToCart function with the item object.

7. Updating Item Quantities

Next, let’s implement the functionality to update item quantities in the cart.

Update the ShoppingCart component code as follows:

import React, { useState } from 'react';

const ShoppingCart = () => {
  const [cartItems, setCartItems] = useState([]);

  const addToCart = (item) => {
    // ... (Add item to cart logic)
  };

  const updateQuantity = (item, quantity) => {
    if (quantity === 0) {
      removeItem(item);
    } else {
      setCartItems(
        cartItems.map((i) => (i.id === item.id ? { ...i, quantity } : i))
      );
    }
  };

  const removeItem = (item) => {
    setCartItems(cartItems.filter((i) => i.id !== item.id));
  };

  return (
    <div>
      {/* Display cart items */}
      {cartItems.length === 0 ? (
        <p>No items in cart</p>
      ) : (
        <ul>
          {cartItems.map((item, index) => (
            <li key={index}>
              {item.name} - {item.quantity}
              <button
                onClick={() => updateQuantity(item, item.quantity - 1)}
              >
                -
              </button>
              <button
                onClick={() => updateQuantity(item, item.quantity + 1)}
              >
                +
              </button>
              <button onClick={() => removeItem(item)}>Remove</button>
            </li>
          ))}
        </ul>
      )}
      {/* Implement add to cart button */}
      {/* Implement checkout button */}
    </div>
  );
};

export default ShoppingCart;

In the updated code, we define the updateQuantity function that takes an item and a quantity as parameters. If the quantity is 0, we call the removeItem function. Otherwise, we update the cartItems state by mapping through the cartItems array and updating the quantity of the item if the item ID matches (setCartItems(cartItems.map((i) => (i.id === item.id ? { ...i, quantity } : i)))). Finally, we define the removeItem function that filters out the item from the cartItems array and updates the state.

We also update the rendering of the cartItems in the return statement to include buttons for updating the quantity (- and +), and a button to remove the item from the cart.

8. Implementing Checkout

Now let’s implement the checkout functionality using Stripe.

Update the ShoppingCart component code as follows:

import React, { useState } from 'react';
import StripeCheckout from 'react-stripe-checkout';

const ShoppingCart = () => {
  const [cartItems, setCartItems] = useState([]);

  const addToCart = (item) => {
    // ... (Add item to cart logic)
  };

  const updateQuantity = (item, quantity) => {
    // ... (Update quantity logic)
  };

  const removeItem = (item) => {
    // ... (Remove item logic)
  };

  const handleToken = (token) => {
    console.log(token);
    // Send the token to your server for processing
  };

  return (
    <div>
      {/* Display cart items */}
      {/* Implement add to cart, update quantity, and remove item buttons */}
      <StripeCheckout
        stripeKey="YOUR_STRIPE_PUBLISHABLE_KEY"
        token={handleToken}
      >
        <button>Checkout</button>
      </StripeCheckout>
    </div>
  );
};

export default ShoppingCart;

In the updated code, we import the StripeCheckout component from react-stripe-checkout and define the handleToken function. This function logs the token to the console and can be used to send the token to your server for processing.

We also add a StripeCheckout component that takes your Stripe Publishable key as the stripeKey prop, and the handleToken function as the token prop. Inside the StripeCheckout component, we add a button for the user to initiate the checkout process.

At this point, you should replace 'YOUR_STRIPE_PUBLISHABLE_KEY' with your actual Stripe Publishable key.

9. Testing the Shopping Cart

Now let’s test the shopping cart functionality.

Update the App component code as follows:

import React from 'react';
import ShoppingCart from './ShoppingCart';

const App = () => {
  const item = {
    id: 1,
    name: 'Example Item',
  };

  return (
    <div>
      <h1>Shopping App</h1>
      <ShoppingCart />
      <button onClick={() => addToCart(item)}>Add to cart</button>
    </div>
  );
};

export default App;

In the code above, we import the ShoppingCart component and define an item object. We also add a button with an onClick event that calls the addToCart function with the item object.

Save your changes and start the development server by running the following command:

npm start

Open your browser and navigate to `http://localhost:3000`. You should see the shopping cart component and a button to add the item to the cart. Click the button, and the item should be displayed in the cart. You can also update the quantity or remove the item from the cart.

10. Completing the Checkout Process

To complete the checkout process, we need to implement the server-side functionality to process the Stripe token and create the charge. This tutorial focuses on the front-end implementation using React, so we will not cover the server-side implementation in detail.

However, we can provide an example of how you can make an API request to your server using fetch and pass the token to your server for processing.

Update the handleToken function in the ShoppingCart component code as follows:

const handleToken = (token) => {
  fetch('/charge', {
    method: 'POST',
    body: JSON.stringify(token),
    headers: {
      'Content-Type': 'application/json',
    },
  })
    .then((response) => response.json())
    .then((data) => {
      console.log(data);
      // Handle the response from your server
    })
    .catch((error) => {
      console.error('Error:', error);
    });
};

In the updated code, we use the fetch function to make a POST request to the /charge endpoint of your server. We pass the Stripe token as the request body, and set the content type to application/json. We also handle the response from your server for further processing.

Update the ShoppingCart component code:

import React, { useState } from 'react';
import StripeCheckout from 'react-stripe-checkout';

const ShoppingCart = () => {
  const [cartItems, setCartItems] = useState([]);

  // ... (Additem to cart, update quantity, remove item functions)

  const handleToken = (token) => {
    fetch('/charge', {
      method: 'POST',
      body: JSON.stringify(token),
      headers: {
        'Content-Type': 'application/json',
      },
    })
      .then((response) => response.json())
      .then((data) => {
        console.log(data);
        alert('Payment Successful!');
        setCartItems([]);
      })
      .catch((error) => {
        console.error('Error:', error);
      });
  };

  return (
    <div>
      {/* Display cart items */}
      {/* Implement add to cart, update quantity, and remove item buttons */}
      <StripeCheckout
        stripeKey="YOUR_STRIPE_PUBLISHABLE_KEY"
        token={handleToken}
      >
        <button>Checkout</button>
      </StripeCheckout>
    </div>
  );
};

export default ShoppingCart;

In the updated code, we handle the response from your server by logging the data to the console, displaying an alert message with “Payment Successful!”, and clearing the cart items by calling setCartItems([]).

Remember to update 'YOUR_STRIPE_PUBLISHABLE_KEY' with your actual Stripe Publishable key.

This completes the implementation of the shopping cart with Stripe integration using React.

Conclusion

In this tutorial, we learned how to build a shopping cart using React and integrate Stripe for payment processing. We created a shopping cart component with functionalities to add items, update quantities, remove items, and initiate the checkout process. We also introduced the react-stripe-checkout library to integrate Stripe into our application and handle the token for server-side processing.

Remember to handle the server-side implementation separately to complete the checkout process and create a charge in Stripe.

Related Post