Build a React Hooks Shopping Cart with useState and useEffect
Tags: react, javascript, webdev, css
Published: 2020-08-20 16:43:47

#Video Walkthrough

{% youtube 1oM2sULKNe0 %}
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. 

```javascript
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;
```

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:

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

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

export default App;
```

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:

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

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

export default Shop;
```
Let's add our inventory as an array labeled items:

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

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:

```javascript
  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>)
```

Above **items**, we will create our first useState hook:

```javascript
const [cart, setCart] = useState([]);
```

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:

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

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:

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

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

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

Change the return statement to include cartItems:

```javascript
  return (
    <div>
      STORE
      <div>{listItems}</div>
      <div>CART</div>
      <div>{cartItems}</div>
    </div>
  );
```

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

```javascript
  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);
  };
```

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:

```javascript
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;
```

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**](https://www.youtube.com/channel/UC3b871DqOlA5tKbizv4J6mg) and the articles are on their way!