E-COMMERCE - Create a shopping cart with React.js

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@jfdesousa7·
0.000 HBD
E-COMMERCE - Create a shopping cart with React.js
<div id="contentMain">


![react.png](https://images.hive.blog/DQmQVsrKNmEtkQQrQkcRXAKs68pjETQ1SMGBaAixn4uPawy/react.png)


<table>
	<tr>
		<td>Today we are going to create a simple shopping cart with React.js we are going to consume the API of <a href="https://fakestoreapi.com/products/ "> Fakestoreapi.com </a> we will also use <a href = "https://material-ui.com/es/"> material-ui </a> that will provide us with Style Components to shape our Web Application, we will also learn to use <a href="https: / /react-query.tanstack.com/ "> react-query </a> to get the API data
</td>
	</tr>
</table>

<h1></h1>
<p><br><br>




<p> We will create a folder on the desktop named <code> shopping-cart </code> / </p>
<p> Once the folder is created, we navigate to it and execute </p>
<div><b></b><br/></div>

<div class="gatsby-highlight">
<pre class="gatsby-code">
<code class="gatsby-code">npx create-react-app .
</code>
</pre>
</div>
<br>


<p> We will install the following modules: </p>

<div class="gatsby-highlight">
<pre class="gatsby-code">
<code class="gatsby-code">npm i react-query @material/core @material/icons
</code>
</pre>
</div>
<br>



<p><b>index.js</b></p>

<div class="gatsby-highlight">
<pre class="gatsby-code">
<code class="gatsby-code">import React from "react";
import ReactDOM from "react-dom";
import { QueryClient, QueryClientProvider } from "react-query";
import App from "./App";
const client = new QueryClient();
ReactDOM.render(
  &lt;QueryClientProvider client={client}>
    &lt;App />
  &lt;/QueryClientProvider>,
  document.getElementById("root")
);
</code>
</pre>
</div>
<br>


<p><b>App.js</b></p>

<div class="gatsby-highlight">
<pre class="gatsby-code">
<code class="gatsby-code">import { useState } from "react";
import { useQuery } from "react-query";
//Components
import Item from "./components/Item";
import CartList from "./components/CartList";
import Navbar from "./components/Navbar";
import Drawer from "@material-ui/core/Drawer";
import LinearProgress from "@material-ui/core/LinearProgress";
import Grid from "@material-ui/core/Grid";
import "./custom.css";
const getProducts = async () =>
  await (await fetch("https://fakestoreapi.com/products/")).json();
const App = () => {
  const { isLoading, error, data } = useQuery("products", getProducts);
  const [cartOpen, setCartOpen] = useState(false);
  const [cartItems, setCartItems] = useState([]);
  const getTotalItems = (cartItems) =>
    cartItems.reduce((acum, i) => acum + i.amount, 0);
  const handleAddItemToCart = (item) => {
    setCartItems((prev) => {
      // Search the item in the array
      const isItemInTheCart = prev.find((i) => i.id === item.id);
      if (isItemInTheCart) {
        return prev.map((i) =>
          i.id === item.id ? { ...i, amount: i.amount + 1 } : i
        );
      }
      return [...prev, { ...item, amount: 1 }];
    });
  };
  const handleRemoveItemFromCart = (id) => {
    setCartItems((prev) => {
      const foundItem = prev.find((i) => i.id === id);
      if (foundItem) {
        if (foundItem.amount === 1) {
          const newArray = prev.filter((i) => i.id !== id);
          return newArray;
        } else {
          return prev.map((i) =>
            i.id === id ? { ...i, amount: i.amount - 1 } : i
          );
        }
      } else {
        return prev;
      }
    });
  };
  if (isLoading) return &lt;LinearProgress></LinearProgress>;
  if (error) return error.message;
  return (
    &lt;>
      &lt;Navbar
        getTotalItems={getTotalItems(cartItems)}
        setCartOpen={setCartOpen}
      >&lt;/Navbar>
      &lt;div className="main">
        &lt;Drawer
          anchor="right"
          open={cartOpen}
          onClose={() => setCartOpen(false)}
        >
          &lt;CartList
            cartItems={cartItems}
            handleAddItemToCart={handleAddItemToCart}
            handleRemoveItemFromCart={handleRemoveItemFromCart}
          />
        &lt;/Drawer>
        &lt;Grid container spacing={3}>
          {data?.map((item) => (
            &lt;Grid key={item.id} item xs={12} sm={4}>
              &lt;Item item={item} handleAddItemToCart={handleAddItemToCart} />
            &lt;/Grid>
          ))}
        &lt;/Grid>
      &lt;/div>
    &lt;/>
  );
};
export default App;
</code>
</pre>
</div>
<br>



<p> <b> We create a custom css file </b> </p>



<p><b>custom.css</b></p>

<div class="gatsby-highlight">
<pre class="gatsby-code">
<code class="gatsby-code">@import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@300&display=swap');
body {
    margin :0;
    padding:0;
    font-family: 'Quicksand', sans-serif;
}
.main {
    padding:40px
}
.cartIcon {
    position: fixed;
    top: 10px;
    right: 140px;
    cursor:pointer;
    z-index: 100;
    background: yellow;
}
aside {
    width:460px;
    margin : 20px;
}
.itemCart {
    display:flex;
    justify-content: space-between;
}
.itemCart img{
    max-width: 80px;
    object-fit: cover;
    margin-left: 40px;
}
.itemCart div{
    flex : 1
}
.itemInfo {
    display: flex;
    justify-content : space-between
}
.buttons {
    display:flex;
    justify-content : space-between
}
</code>
</pre>
</div>
<br>


<h3>Components</h3>


<p><b>components/Navbar.js</b></p>

<div class="gatsby-highlight">
<pre class="gatsby-code">
<code class="gatsby-code">import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import IconButton from "@material-ui/core/IconButton";
import Badge from "@material-ui/core/Badge";
import Menu from "@material-ui/core/Menu";
import AddShoppingCart from "@material-ui/icons/AddShoppingCart";
const useStyles = makeStyles(() => ({
  grow: {
    flexGrow: 1,
  }
}));
export default function Navbar({ getTotalItems, setCartOpen }) {
  const classes = useStyles();
  const [anchorEl, setAnchorEl] = React.useState(null);
  const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React.useState(null);
  const isMenuOpen = Boolean(anchorEl);
  const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);
  const handleMobileMenuClose = () => {
    setMobileMoreAnchorEl(null);
  };
  const handleMenuClose = () => {
    setAnchorEl(null);
    handleMobileMenuClose();
  };
  const menuId = "primary-search-account-menu";
  const renderMenu = (
    &lt;Menu
      anchorEl={anchorEl}
      anchorOrigin={{ vertical: "top", horizontal: "right" }}
      id={menuId}
      keepMounted
      transformOrigin={{ vertical: "top", horizontal: "right" }}
      open={isMenuOpen}
      onClose={handleMenuClose}
    >&lt;/Menu>
  );
  const mobileMenuId = "primary-search-account-menu-mobile";
  const renderMobileMenu = (
    &lt;Menu
      anchorEl={mobileMoreAnchorEl}
      anchorOrigin={{ vertical: "top", horizontal: "right" }}
      id={mobileMenuId}
      keepMounted
      transformOrigin={{ vertical: "top", horizontal: "right" }}
      open={isMobileMenuOpen}
      onClose={handleMobileMenuClose}
    >&lt;/Menu>
  );
  return (
    &lt;div className={classes.grow}>
      &lt;AppBar position="static">
        &lt;Toolbar>
          &lt;b>Shopping Cart&lt;/b>&nbsp;&nbsp; | &nbsp;&nbsp;
          &lt;div className={classes.grow} />
          &lt;div onClick={() => setCartOpen(true)}
          >
            &lt;IconButton aria-label="show 4 new mails" color="inherit">
              &lt;Badge badgeContent={getTotalItems} color="secondary">
                &lt;AddShoppingCart />
              &lt;/Badge>
            &lt;/IconButton>
          &lt;/div>
        &lt;/Toolbar>
      &lt;/AppBar>
      {renderMobileMenu}
      {renderMenu}
    &lt;/div>
  );
}
</code>
</pre>
</div>
<br>



<p><b>components/Item.js</b></p>

<div class="gatsby-highlight">
<pre class="gatsby-code">
<code class="gatsby-code">import Card from "@material-ui/core/Card";
import { makeStyles } from '@material-ui/core/styles';
import CardActionArea from "@material-ui/core/CardActionArea";
import CardActions from "@material-ui/core/CardActions";
import CardContent from "@material-ui/core/CardContent";
import CardMedia from "@material-ui/core/CardMedia";
import Button from "@material-ui/core/Button";
const useStyles = makeStyles({
    root: {
      maxWidth: 345,
    },
  });
export default function Item({item, handleAddItemToCart }) {
    const classes = useStyles();
  return (
    &lt;Card className={classes.root}>
      &lt;CardActionArea>
        &lt;CardMedia
          component="img"
          alt={item.title}
          height="200"
          image={item.image}
          title={item.title}
        />
        &lt;CardContent>
          {item.description}
        &lt;/CardContent>
      &lt;/CardActionArea>
      &lt;CardActions>
      &lt;Button size="small" color="secondary">
          $ {item.price}
        &lt;/Button>
        &lt;Button size="small" color="primary" onClick = { () => handleAddItemToCart(item)}>
          Add to Cart
        &lt;/Button>
      &lt;/CardActions>
    &lt;/Card>
  );
}
</code>
</pre>
</div>
<br>



<p><b>components/CartList.js</b></p>

<div class="gatsby-highlight">
<pre class="gatsby-code">
<code class="gatsby-code">import CartItem from "./CartItem";
const CartList = ({ cartItems, handleAddItemToCart, handleRemoveItemFromCart  }) => {
  const calculeTotal = cartItems.reduce(
    (sum, i) => sum + i.amount * i.price,
    0
  );
  return (
    &lt;aside>
      &lt;h1>Cart&lt;/h1>
      {cartItems.length === 0 ? &lt;h3>No products yet...&lt;/h3> : null}
      &lt;div>
        {cartItems.map((i) => (
          &lt;CartItem item={i} handleAddItemToCart={handleAddItemToCart} handleRemoveItemFromCart={handleRemoveItemFromCart} />
        ))}
      &lt;/div>
      &lt;h2>Total: {calculeTotal.toFixed(2)}&lt;/h2>
    &lt;/aside>
  );
};
export default CartList;
</code>
</pre>
</div>
<br>



<p><b>components/CartItem.js</b></p>

<div class="gatsby-highlight">
<pre class="gatsby-code">
<code class="gatsby-code">import Button from "@material-ui/core/Button";
const CartItem = ({ item, handleAddItemToCart, handleRemoveItemFromCart }) => {
  return (
    &lt;aside>
      &lt;div className="itemCart">
        &lt;div>
          &lt;h3>{item.title}&lt;/h3>
          &lt;div className="itemInfo">
            &lt;p>Precio: ${item.price}&lt;/p>
            &lt;p>Total: ${(item.amount * item.price).toFixed(2)}&lt;/p>
          &lt;/div>
          &lt;div className="buttons">
            &lt;Button onClick={ () => handleRemoveItemFromCart(item.id)} size="small" disableElevation variant="contained">
              -
            &lt;/Button>
            &lt;p> {item.amount}</p>
            &lt;Button
              size="small"
              disableElevation
              variant="contained"
              onClick={() => handleAddItemToCart(item)}
            >
              +
            &lt;/Button>
          &lt;/div>
        &lt;/div>
        &lt;img src={item.image} />
      &lt;/div>
    &lt;/aside>
  );
};
export default CartItem;
</code>
</pre>
</div>
<br>




<br/>


<table><tr><td><h3>And with those friends we reached the end of the tutorial, I hope you enjoyed it and until next time! </h3></td>
</tr>
</table>
<br/>



<h4>Visit my official website for budges and much more</h4>

<center><a href="https://tupaginaonline.net" target="_blank"><b>TupaginaOnline.net</b></a></center>


</div>
👍 , , , , , ,