React has grown to be an industry standard for building interactive user interfaces, it simplifies how complex applications are developed. One of the challenges developers encouter when building applications is how data is being managed across different components. This is where React Context Api comes in. Context API provides a way to pass data through the component trees without having to pass props manually at every level, with the help of Context API we can effectively manage the state of a shopping cart across all components without passing props down the component tree.
In this article we will use the Context API to build a robust shopping cart in a React Application, we will be building the various components, setting up context API, and implementing a payment gateway feature to create a seamless shopping experience for users.
Here is the link to the Live Demo softmarts.vercel.app
Understanding Context Api
Prerequisite
To successfully follow this tutorial on building a React shopping cart with the Context API and Integrating Stripe Payment Gateway, it is essential to have a solid understanding of the following:
1. Familiarity with React concepts like components, state management, props, and lifecycle methods is necessary.
2. Knowledge of modern JavaScript features such as arrow functions, template literals, destructuring, and spread/rest operators is crucial for writing React code effectively.
3. Ensure that Node.js and npm (Node Package Manager) are installed on your machine to set up and run the React project locally.
Getting Started: Creating a React App and Installing other dependencies
- Navigate to your project folder, open your terminal
- Run the following command to create a new project using vite npm create @ latest vite
- You will be prompted to name your project, give it any name of your choice, I will name mine softmart.
- After naming your project, you will be prompted to select a variant. Choose "Javascript" and press enter to proceed.
- Navigate to your newly created project directory by running cd "name of your project"
- Launch your application in development mode by running npm run dev from your terminal, This will start the development server, then navigate to the url provided( http://localhost:5173) on your browser.
Installing Tailwind Css
- Run this command on your terminal to install tailwindcss and create a tailwind.config.js file
- Open the tailwind.config.js file in your project directory and add the paths to all your template files .
- Next, navigate to your index.css file, clear all the existing code, Then input the following code. This code imports the base styles, component classes, and utility classes from Tailwind CSS.
Building Our App Component
Setting up component structure
The Navbar Component
The ProductPage Component
The CartPage
Navigating between Pages
Setting up the cart context
To establish the foundation for sharing cart data across our application, let's leverage the Context API in React. Follow these steps to set up the cart context:
Create Context File:
- Navigate to the src directory of your project.
- Inside the src directory, create a new folder named context.
- Within the context folder, create a new file named cart.jsx. This file will serve as the container for our cart context.
Define Cart Context:
- Open the cart.jsx file.
- Begin by importing createContext from React.
- Create a new context object called CartContext using createContext().
Here's how you can implement this in code:
- After creating the context object, wrap the component that needs access to the shared data with a provider component.
- The provider component accepts a value prop that holds the shared data.
- Any component that is a child of the Provider component can access that shared data.
- We utilize the find method to determine whether the item being added already exists in the cart.
- If it does, the existingItem variable holds a reference to that item.
- Then we check if the item exists in the cart, we increment its quantity by mapping over the cartItems array and adjusting the quantity of the matching item.
- If the item is not yet in the cart, we append it to the cart with a quantity of 1 by spreading the existing cartItems array and appending the new item with an initial quantity of 1.
- Finally, we update the state of the cart items using the setCartItems function, passing in the updated array of cart items.
Removing Item from the Cart: Lets create a function to implent the remove from cart feature, copy the code below:
In the code above:
- We utilize the find method to determine whether the item being removed exists in the cart. If it does, the existingItem variable holds a reference to that item.
- We also check if the existing item's quantity is equal to 1. If the quantity is indeed 1, it means that removing one more instance of the item will result in an empty cart for that item.
- If the item exists in the cart and its quantity is 1, we remove it from the cart by filtering out the item with a quantity of 1 from the cartItems array.
- If the item exists in the cart and its quantity is greater than 1, we decrement its quantity by mapping over the cartItems array and reducing the quantity of the matching item by 1.
- The reduce method is used to iterate over all items in the cartItems array and accumulate a total value.
- Within the reduce method, we provide a callback function with two parameters: total and item. The total parameter represents the accumulated total value, while the item parameter represents each item in the cartItems array.
- In each iteration, we calculate the subtotal for the current item by multiplying its price (item.price) by its quantity (item.quantity). This gives us the total price for all instances of the item in the cart.
- The reduce method accepts an initial value as its second argument. In this case, we set the initial value to 0, indicating that the accumulation starts from zero.
- The reduce method returns the final accumulated total value, which represents the total cost of all items in the shopping cart, taking into account their respective quantities.
Clear Cart: Let's move on to creating a function that will be used for clearing every item in our cart, copy the code below:
In the code above:
- The clearCart function clears the contents of the shopping cart by setting the cartItems state to an empty array.
- This `useEffect` hook is responsible for updating the `localStorage` whenever the `cartItems` state changes.
- The second argument of the `useEffect` hook is an array `[cartItems]`, which specifies that the effect should be triggered whenever the `cartItems` state changes.
- Within the effect function, `localStorage.setItem()` is called to update the `cartItems` data in the browser's local storage. The `setItem()` method takes two arguments: a key `"cartItems"` and a value `JSON.stringify(cartItems)`.
- Before storing the `cartItems` data in the local storage, it is converted to a JSON string using `JSON.stringify()`. This is necessary because `localStorage` can only store string data.
- Since the effect depends on the `cartItems` state, it will be executed whenever `cartItems` changes, ensuring that the local storage is always synchronized with the latest cart data.
To ensure that the cart's contents are preserved during browser refreshes, we'll configure our application to initialize the cartItems state by retrieving data from local storage. If the data isn't available, we'll set cartItems to an empty array.
In the code above:
- The useState hook is used to initialize the cartItems state variable. It is declared with an initial value obtained from localStorage or an empty array if no cart items are found in localStorage.
- The localStorage.getItem("cartItems") method retrieves the value associated with the key "cartItems" from the browser's localStorage.
- The ternary operator ? is used to check if a value exists for "cartItems" in localStorage. If a value is found, it is parsed from a JSON string to a JavaScript object using JSON.parse(localStorage.getItem("cartItems")). This parsed value becomes the initial state of cartItems.
- If no value is found for "cartItems" in localStorage, the expression evaluates to null, and the ternary operator sets the initial state of cartItems to an empty array [].
Consuming the Cart Context
Consuming in the Product Page
Its time to spice our produc page, by making it more interactive, in this session you will see howw to consume the the functions from the cartContext, navigate to the productPage.jsx and include the following code:
- The useContext hook is imported from the React library. It allows functional components to consume context values provided by a ContextProvider.
- The CartContext is imported from (../Context/Cart). This context contains the necessary data and functions related to the shopping cart.
- Within the Products component, the useContext hook is used to consume the CartContext. This allows the component to access the cartItems, addToCart, and removeFromCart values provided by the context.
- The expression {!isCart(product) ? (...) : (...)} performs a conditional check. If isCart(product) returns false (indicating the product is not in the cart), the first block of JSX elements is rendered. Otherwise, if isCart(product) returns true (indicating the product is already in the cart), the second block of JSX elements is rendered.
- In the first block, when the product is not in the cart, a button with the text "Add to Cart" is rendered. Clicking this button triggers the addToCart function to add the product to the cart.
- In the second block, when the product is already in the cart, three elements are rendered: an "Add" button, the quantity of the product in the cart, and a "Minus" button. Clicking the "Add" button increments the quantity of the product in the cart, while clicking the "Minus" button decrements the quantity.
- The onClick handlers attached to the buttons call the addToCart and removeFromCart functions.
Consuming in the NavPage
Consuming in the CartPage
- The useContext hook is utilized to access the CartContext, allowing the component to retrieve essential data and functions related to the shopping cart.
- The component begins by rendering the overall summary of the cart, including a heading for "Cart Summary" and displaying the subtotal of all items in the cart.
- It iterates over the cartItems array retrieved from the context and renders individual items within the cart. Each item is displayed with its image, title, price, and quantity. Users can see a preview of the item and its associated details.
- For each item, buttons are provided to adjust its quantity in the cart. Users can increment or decrement the quantity of an item using the "Add" and "Minus" buttons respectively. These actions are facilitated by the addToCart and removeFromCart functions obtained from the context.
- Finally, a checkout button is displayed at the bottom of the page, allowing users to proceed with their purchase. This button doesn't have functionality implemented within the provided code snippet, but it typically would trigger actions to complete the checkout process, such as sending the cart data to a backend server for processing.
Integrating Stripe payment gateway
To elevate the functionality of our project, we'll now integrate the Stripe payment gateway, enabling users to make secure online payments for their items.
- Setting Up Stripe Account: Begin by navigating to the Stripe website in your browser. Click on the "Sign In" button to access the platform. If you don't have an account yet, click on "Sign Up" and follow the prompts to create your Stripe account. After successfully creating your account, you'll be redirected to a page where you'll find your secret key. Be sure to copy this key as we'll need it later in the process.
- Backend Setup: Outside your React frontend project, create a new folder named [your-project]-be to house the backend code responsible for communicating with Stripe. Within this folder, create a new file named Server.js and paste your secret key there, ensuring to comment it out for security purposes.
- Creating Backend: Now, let's create a full backend to handle Stripe requests. Navigate to your backend folder in the terminal and run npm init --yes to generate a package.json file. Next, install the necessary dependencies by running npm install express cors stripe. These packages will provide the essential functionality for setting up our backend.
Building the Backend (Server.js)
- Import Dependencies: We import the express framework for creating our server, cors middleware for handling cross-origin resource sharing, and stripe library for interacting with Stripe's API. The stripe library is initialized with your secret API key.
- Set up Express App: We create an Express application, enable CORS, set up static file serving from a public directory, and parse JSON requests.
- Define Checkout Endpoint: We define a POST endpoint /checkout to handle checkout requests. This endpoint will receive data about the items to be purchased.
- Handle Checkout Request:We extract the items array from the request body, which contains the items to be purchased.
- Create Line Items for Checkout Session: We map over each item in the cartItems array to create line items required for the Stripe checkout session. Each line item includes the product's name, price in cents, and quantity.
- Create Stripe Checkout Session: We use the stripe.checkout.sessions.create method to create a new checkout session with specified parameters, including payment method types, line items, mode, and success/cancel URLs.
- Return Checkout Session URL: Finally, we send back a JSON response containing the URL of the created checkout session to redirect the user to Stripe's payment page.
- Start Server: Finally, we start the Express server, listening on port 4000. This allows the server to receive incoming requests and handle them accordingly, including the checkout requests to initiate payment via Stripe.
- Run Backend Server: To start the backend server and make it operational, navigate to the backend directory in your terminal and execute the command npm start.
Submiting the user cart to the backend
- Navigate to your Frontend project and run npm run dev, to start your frontend application
- Navigate to your backend project and run npm start to start your backend application
Here is the link to the GitHub repository of the project Timmydee/Softmarts
Here is the link to the Live Demo softmarts.vercel.app
Post a Comment
0Comments