Build a React Hooks Shopping Cart with useState and useEffect

Anthony Santonocito - Aug 20 '20 - - Dev Community

Video Walkthrough


subscribe on youtube for more content.

Article Explanation of Hooks

In this article, we will use hooks to create a video game shop and shopping cart.

First, I will show an example of how to use the useState hook.

import React, { useState } from "react";

const Shop = () => {
  const [open, setOpen] = useState(true);
  console.log(open)

  const closeStore = () => {
    setOpen(false)
}
  return(
    <div>
    <input type="submit" value="close" onClick={() => closeStore()} />
    </div>
)
}

export default Shop;
Enter fullscreen mode Exit fullscreen mode

In this example, open is a key that holds the useState argument as its value. useState(true), open = true.

setOpen is a function that takes a value as an argument.

setOpen will set open to the new value passed to setOpen.

setOpen(false), sets open = false

This shows a button that can be clicked in order to change the value of open from true to false.

Let's try a more complex use case.

In App.js we will return a div with our soon to be created Shop component:

import React from "react";
import Shop from "./shop/Shop";

function App() {
  return (
    <div>
      <Shop />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

We will create the shop component next. Create a folder in src named shop. Then create a file in that folder named Shop.js

The finished Shop.js code is at the bottom of the article.

We are going to return an empty functional component to get us started:

import React, { useState, useEffect } from "react";

const Shop = () => {
    return <div />
}

export default Shop;
Enter fullscreen mode Exit fullscreen mode

Let's add our inventory as an array labeled items:

const Shop = () => {
  const items = [
    {
      id: 1,
      name: "overwatch",
      price: 20,
    },
    {
      id: 2,
      name: "minecraft",
      price: 32,
    },
    {
      id: 3,
      name: "fortnite",
      price: 51,
    },
  ];
  return <div />
}
Enter fullscreen mode Exit fullscreen mode

We are only selling these three video games. We need to display them. So, we will create a new formatted array called listItems using .map(). Now, we should return listItems:

  const listItems = items.map((el) => (
    <div key={el.id}>
      {`${el.name}: $${el.price}`}
      <input type="submit" value="add" onClick={() => addToCart(el)} />
    </div>
  ));

return(<div>{listItems}</div>)
Enter fullscreen mode Exit fullscreen mode

Above items, we will create our first useState hook:

const [cart, setCart] = useState([]);
Enter fullscreen mode Exit fullscreen mode

The const cart is where we will hold our cart state. We can call setCart() and pass in the state changes we want to make to cart. Let's create our addToCart function using setCart:

  const addToCart = (el) => {
      setCart([...cart, el]);
  };
Enter fullscreen mode Exit fullscreen mode

addToCart takes the element selected and adds it to the cart array.

We are going to display the cart, in our app, under our store. First, make a new formatted array from the cart array:

  const cartItems = cart.map((el) => (
    <div key={el.id}>
      {`${el.name}: $${el.price}`}
      <input type="submit" value="remove" onClick={() => removeFromCart(el)} />
    </div>
  ));
Enter fullscreen mode Exit fullscreen mode

We can create our removeFromCart function using the filter method. note* We will make a copy of the cart state before filtering:

  const removeFromCart = (el) => {
    let hardCopy = [...cart];
    hardCopy = hardCopy.filter((cartItem) => cartItem.id !== el.id);
    setCart(hardCopy);
  };
Enter fullscreen mode Exit fullscreen mode

Change the return statement to include cartItems:

  return (
    <div>
      STORE
      <div>{listItems}</div>
      <div>CART</div>
      <div>{cartItems}</div>
    </div>
  );
Enter fullscreen mode Exit fullscreen mode

Finally, we will keep track of the total using useState and useEffect:

  const [cartTotal, setCartTotal] = useState(0);

  useEffect(() => {
    total();
  }, [cart]);

  const total = () => {
    let totalVal = 0;
    for (let i = 0; i < cart.length; i++) {
      totalVal += cart[i].price;
    }
    setCartTotal(totalVal);
  };
Enter fullscreen mode Exit fullscreen mode

The useEffect hook contains an arrow function. Inside the arrow function, we call our total function.

The second argument in useEffect is the dependency array containing [cart].

useEffect will detect changes in the variables named within its dependency array. When it detects a change, it will run again.

Every time an item is added or removed from the cart, useEffect will detect a change in cart and run the total function.

Finally, place total in your return:

import React, { useState, useEffect } from "react";

const Shop = () => {
  const [cart, setCart] = useState([]);
  const [cartTotal, setCartTotal] = useState(0);
  const items = [
    {
      id: 1,
      name: "overwatch",
      price: 20,
    },
    {
      id: 2,
      name: "minecraft",
      price: 32,
    },
    {
      id: 3,
      name: "fortnite",
      price: 51,
    },
  ];

  useEffect(() => {
    total();
  }, [cart]);

  const total = () => {
    let totalVal = 0;
    for (let i = 0; i < cart.length; i++) {
      totalVal += cart[i].price;
    }
    setCartTotal(totalVal);
  };

  const addToCart = (el) => {
      setCart([...cart, el]);
  };

  const removeFromCart = (el) => {
    let hardCopy = [...cart];
    hardCopy = hardCopy.filter((cartItem) => cartItem.id !== el.id);
    setCart(hardCopy);
  };

  const listItems = items.map((el) => (
    <div key={el.id}>
      {`${el.name}: $${el.price}`}
      <input type="submit" value="add" onClick={() => addToCart(el)} />
    </div>
  ));

  const cartItems = cart.map((el) => (
    <div key={el.id}>
      {`${el.name}: $${el.price}`}
      <input type="submit" value="remove" onClick={() => removeFromCart(el)} />
    </div>
  ));

  return (
    <div>
      STORE
      <div>{listItems}</div>
      <div>CART</div>
      <div>{cartItems}</div>
      <div>Total: ${cartTotal}</div>
    </div>
  );
};

export default Shop;
Enter fullscreen mode Exit fullscreen mode

Watch the video for more! Next, we will refactor this code to use Redux. After that, we will start making http requests using the fetch api and redux-thunk. Finally, we will convert the project to redux-saga. The videos are up on youtube already Youtube Channel Link and the articles are on their way!

. . .
Terabox Video Player