Building an e-commerce website with React and 8base
Tags: react, 8base, javascript, webdev
Published: 2019-12-05 16:21:17

---
title: Building an e-commerce website with React and 8base
published: true
date: 2019-12-05 14:26:38 UTC
tags: react,8base,javascript,webdev
canonical_url: https://blog.logrocket.com/building-an-e-commerce-website-with-react-and-8base/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/eexxyrl9aj2ntbxvail1.png
---
**Written by [Ogundipe Samuel](https://blog.logrocket.com/author/osamuel/)**✏️

In 2018, the total value of online shopping markets was estimated to be around $2.84 trillion. Companies like Amazon, Walmart, and Alibaba top the charts. Through their massive platforms, these giants have opened a new window for small businesses to also operate and own their e-commerce stores.

In this tutorial, we will build an e-commerce website using React for the frontend and 8base for the backend.

> N/B: To follow this tutorial, a basic understanding of React and Node.js is required. Please ensure that you have Node and npm/yarn installed before you begin. We’ll also be making use of some GraphQL queries in the project, so some familiarity with GraphQL will be helpful.

### What is React?

[React](https://reactjs.org/) is a component-based JavaScript library for building user interfaces. It allows us to build encapsulated components that manage their state, then compose them to make complex UIs.

### What is 8base?

8base is a GraphQL backend that lets javascript developers quickly deliver enterprise applications using full-stack JavaScript. It is a front-end framework agnostic, therefore it enables developers to create customer-facing applications however they choose to.

We will use 8base as a backend database layer for our app. This is where we will store the products for our e-commerce website.

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

### Getting Started

8base offers a wide array of features to help developers build performant applications at a faster and much easier rate. Using the 8base Console, you can build your backend using a simple GUI that allows you to do things like:

- Define data schemas: create tables/table relationships
- Set permission and authorization roles
- Organize multiple projects into **Workspaces**
- Design queries using the API explorer (based on GraphQL)
- Manage files

To get started using 8base, follow the steps listed below:

- Create an account on [8base](https://auth.8base.com/login?state=g6Fo2SBrb283dEtrOGU4bndGUTFGQUVyZWNwcFlrNzVFVWw5Z6N0aWTZIHByblBCMU84VWREN1ZXLVJvVFRkclpYUjE0ai01cDJOo2NpZNkgcUdIWlZ1NUN4WTVrbGl2bTI4T1BMam9wdnNZcDBiYUQ&client=qGHZVu5CxY5klivm28OPLjopvsYp0baD&protocol=oauth2&response_type=token%20id_token&redirect_uri=https%3A%2F%2Fapp.8base.com%2Fauth%2Fcallback&scope=openid%20email%20profile&mode=signUp&nonce=x0M6LCwpVoLZ3u1HqwPuY.Qi1.YSBj6M&auth0Client=eyJuYW1lIjoiYXV0aDAuanMiLCJ2ZXJzaW9uIjoiOS4xMS4xIn0%3D). You can start using 8base for free.

![8base](https://blog.logrocket.com/wp-content/uploads/2019/12/8base-nocdn.jpeg)

- After sign up is complete, click on the Data Builder button to navigate to the [Data](https://app.8base.com/data/?source=post_page---------------------------) menu and click on “New Table” to start building your backend.

![john-paul-nocdn.png](https://blog.logrocket.com/wp-content/uploads/2019/12/JohnPauls-workspace-nocdn.png)

- After your new table is loaded, you’ll be taken to the schema to begin defining fields. Let’s take a look around and note a couple of things. On the left, you’ll see there are `System Tables` and `Your Tables`.

Every new 8base workspace automatically comes prepackaged with some built-in tables. These tables are used to handle things like Files, Settings, and Permissions and can all be accessed through the 8base GraphQL API.

- Go ahead and create a table, `Products, which will consist of the following fields:`

**name: “”**  
type: Field type is text.  
description: “This will be the name of the product”

**price: “”**  
type: Field type is number.  
description: “This field will hold the price of our product.”

**description: “”**  
type: Field type is text.  
description: “This field will hold the description of our product.”

**image: “”**  
type: Field type is file.  
description: “This field will hold the image of our product.”

![fields-nocdn.png](https://blog.logrocket.com/wp-content/uploads/2019/12/fields-nocdn.png)

- We need some sample posts to work with, so let’s add some sample data. Next to the schema menu icon where we created our schema, click on the Data tab and add a sample Product record by setting a title and body.

![image preview](https://blog.logrocket.com/wp-content/uploads/2019/12/image_preview-nocdn.png)

- Next, copy the API endpoint URL (available on the bottom left) — this is the single endpoint for communication between your frontend and your 8base backend.

![API endpoint](https://blog.logrocket.com/wp-content/uploads/2019/12/API-endpoint-nocdn.png)

- Finally, for this tutorial, we’re going to allow open access to Guests by default so that dealing with authentication is optional. To allow guest access to your new Products table, navigate to `Settings > Roles > Guest,` and check the appropriate boxes under Products and Files.

All unauthenticated users who access your API endpoint are assigned the role of Guest by default.

We won’t cover authentication in this tutorial. You can see how authentication should be handled in more detail [here](https://docs.8base.com/docs/authentication?utm_source=scotchio&utm_medium=blog&utm_campaign=codebeast&source=post_page---------------------------).

![workspace-nocdn.png](https://blog.logrocket.com/wp-content/uploads/2019/12/settings-johnpaul-nocdn.png)

In just a few simple steps, we’ve finished setting up a production-ready CMS backend using 8base. Let’s start work on the frontend side of the application.

### Using React

To start using React, we must first install it. The fastest way to get up and running is by using [CRA](https://create-react-app.dev/).

If you don’t already have it installed on your development machine, open your terminal and run the following command:

```jsx
npx create-react-app
```

### Generate a React project

Once the installation is successful, you can now bootstrap a new react project. To create our project run the following command:

```jsx
npx create-react-app shopping-cart
```

Start the React app server by running `npm start` in a terminal in the root folder of your project.

![React](https://blog.logrocket.com/wp-content/uploads/2019/12/react-edit-nocdn.png)

### Creating our layout

Let’s start creating the layout for our project. Our app will have 5 different components.

- **Navbar** : To hold our navigation and cart icon
- **Products** : To display a list of products.  
– **Product** : The markup for a single product
- **Footer** : The footer of our app
- **Cart** : To hold the items in our cart

We will make use of bootstrap in our project, so first let’s include it. Open up your `index.html` in the public folder and add the following link tag to the head section:

```jsx
// ./public/index.html
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
```

Now we can make use of bootstrap classes in our application.

Next, create a components folder and create the following components inside it: Navbar.js, Products.js, Product.js, Footer.js, Cart.js.

Open up the Navbar.js and add the following code:

```jsx
// src/components/Navbar.js
import React from 'react';

const Navbar = () => {
  return (
    <nav className="navbar navbar-light bg-light">
      <a className="navbar-brand">Shoppr</a>
        <button className="btn btn-outline-success my-2 my-sm-0" type="submit">Cart</button>
    </nav>
  );
};
export default Navbar;
```

Open up the Footer.js and add the following code to it:

```jsx
// src/components/Footer.js 
import React from 'react';
import '../App.css';

const Footer = () => {
  return (
      <footer className="page-footer font-small bg-blue pt-4">
        <div className="container text-center text-md-left">
          <div className="row">
            <div className="col-md-6 mt-md-0 mt-3">
              <h5 className="text-uppercase font-weight-bold">Contact Us</h5>
              <p>You can contact us on 234-8111-111-11</p>
            </div>
            <div className="col-md-6 mb-md-0 mb-3">
              <h5 className="text-uppercase font-weight-bold">Return Policy</h5>
              <p>We accept returns after 7 days max</p>
            </div>
          </div>
        </div>
        <div className="footer-copyright text-center py-3">© 2019 Copyright:
          <span> Shoppr</span>
        </div>
      </footer>
  );
};
export default Footer;
```

Our footer needs some styling so we’d add the following styles to the `App.css` file:

```jsx
// src/App.css
footer {
  position: absolute;
  bottom: 0;
  width: 100%;
  background-color: #333;
  color:#fff;
}
```

Before we create our products component we need to query 8base to send us our product details to display. Let’s do that now.

### Connecting to the 8base backend with GraphQL

To connect our application to the backend we need to install a couple of GraphQL packages. One of the libraries we’d use is [apollo-boost](https://www.npmjs.com/package/apollo-boost), it provides a client for connecting to the GraphQL backend using a URI.

The URI is the endpoint provided by 8base and is available on the [data](https://app.8base.com/data) page of the dashboard.

Run the following command in your terminal to install the necessary packages:

```jsx
npm install apollo-boost graphql graphql-tag react-apollo
```

Once successful, go ahead and update the `index.js` file in the src directory to the following code:

```jsx
import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import { ApolloProvider } from "react-apollo";
    import ApolloClient from "apollo-boost";
    import * as serviceWorker from './serviceWorker';
    
    const client = new ApolloClient({
      uri: "<YOUR_8BASE_ENDPOINT>"
    });
    
    ReactDOM.render(
      <ApolloProvider client={client}>
        <App />
      </ApolloProvider>,
      document.getElementById('root')
    );
    
    serviceWorker.unregister();
```

We’ve wrapped our entire application with the `ApolloProvider` that takes a single prop, the client. The ApolloProvider loads the 8base table schema, which gives you access to all properties of the data model inside your application.

### Displaying our products

We’ve been able to load our table schema from 8base into our application. The next step is to fetch and display our products.

Create a `product-list` folder under the component folder and then create an `index.js` file and add the following to it:

```jsx
// src/components/product-list/index.js
import gql from "graphql-tag";
import { graphql } from "react-apollo";

const PRODUCTS_QUERY = gql`
  query {
    productsList {
      items {
        id
        createdAt
        name
        price
        description
        image {
          downloadUrl
        }
      }
    }
  }
`;
export default PRODUCTS_QUERY;
```

Here, we create a constant called `PRODUCTS_QUERY` that stores the query. The `gql` function is used to parse the plain string that contains the GraphQL code.

We’ve already populated the backend with some data. To test if our query works properly, 8base provides a handy GraphQL explorer specifically for this. In the menu of your 8base dashboard click on the API explorer icon and run the query.

![API explorer](https://blog.logrocket.com/wp-content/uploads/2019/12/API-explorer-nocdn.png)

Now, we are certain our query works as it should. Let’s go ahead and create our product’s components.

Open up your the `Products.js` component and add the following code to it:

```jsx
// src/components/Products.js
import React, { Component } from 'react';
import { Query } from 'react-apollo';
import PRODUCTS_QUERY from './product-list/index';
import Product from './Product';
import Navbar from './Navbar';

class Products extends Component {

   constructor(props) {
    super(props);
    this.state = {
      cartitems: []
    };
   }

   addItem = (item) => {
      this.setState({
          cartitems : this.state.cartitems.concat([item])
      });
    }

  render() {
    return (
      <Query query={PRODUCTS_QUERY}>
       {({ loading, error, data }) => {

          if (loading) return <div>Fetching</div>
          if (error)   return <div>Error</div>

          const items = data.productsList.items;
          return (
            <div>
              <Navbar/>
              <div className="container mt-4">
                <div className="row">
                   {items.map(item => <Product key={item.id} product={item} addItem={this.addItem} />)}
                </div>
              </div>
            </div>
          )
        }}
      </Query>
    );
  }

};
```

export default Products;Here, we wrap our products with the `<Query/>` component and pass the `PRODUCTS_QUERY` as props.

Apollo injected several props into the component’s `render prop function`. These props themselves provide information about the state of the network request:

1. `loading`: This is `true` as long as the request is still ongoing and the response hasn’t been received.
2. `error`: In case the request fails, this field will contain information about what exactly went wrong.
3. `data`: This is the actual data that was received from the server. It has the `items` property which represents a list of `product` elements.

Finally, we loop through all the received items and pass them as a prop to our Product component. Before we see what it looks like, let’s create our `Product` component.

Open up your `Product.js` and add the following code to it:

```jsx
// src/components/Product.js
import React from 'react';

const Product = (props) => {
  return (
      <div className="col-sm-4">
          <div className="card" style={{width: "18rem"}}>
            <img src={props.product.image.downloadUrl} className="card-img-top" alt="shirt"/>
            <div className="card-body">
              <h5 className="card-title">{props.product.name}</h5>
              <h6 className="card-title">$ {props.product.price}</h6>
              <button className="btn btn-primary" onClick={() => props.addItem(props.product)}>Buy now</button>
            </div>
          </div>
      </div>
  );
}
export default Product;
```

Our `Product.js` is a functional component that receives product details via props and displays them.

We also call the `addItem` function on the click method to add the current product to the cart when it is clicked.

Now, all our components are setup we need to import them in our `App.js` component which is our base component. Open it up and add the following to it:

```jsx
// src/App.js
import React from 'react';
import './App.css';
import Footer from './components/Footer';
import Products from './components/Products';

function App() {
  return (
    <div className="App">
      <Products />
      <Footer/>
    </div>
  );
}
export default App;
```

Go to, https://localhost:3000 in your browser and you will see the following:

![shirts-nocdn.png](https://blog.logrocket.com/wp-content/uploads/2019/12/example-shirts-ecommerce-nocdn.png)

At this point, we have a store that displays products, we need to add functionality to add items to our cart.

### Adding the Cart functionality

To add our cart functionality we’d need to add some more methods to our components.

Update your `products.js` to this:

```jsx
// src/components/products.js
import React, { Component } from 'react';
import { Query } from 'react-apollo';
import PRODUCTS_QUERY from './product-list/index';
import Product from './Product';
import Cart from './Cart';
import Navbar from './Navbar';

class Products extends Component {

  constructor(props) {
    super(props);
    this.state = {
      cartitems: []
    };
    this.addItem = this.addItem.bind(this);
  }

    addItem(item){
      this.setState({
          cartitems : this.state.cartitems.concat([item])
      });
    }

    showModal = () => {
      this.setState({ show: true });
    };

    hideModal = () => {
      this.setState({ show: false });
    };

  render() {

    return (
          <Query query={PRODUCTS_QUERY}>
           {({ loading, error, data }) => {

              if (loading) return <div>Fetching</div>
              if (error)   return <div>Error</div>

              const items = data.productsList.items;
              const itemssent = this.state.cartitems;

              return (
                <div>
                 <Navbar cart={itemssent} show={this.showModal} />
                 <Cart show={this.state.show} items={itemssent} handleClose={this.hideModal}>
                  </Cart>
                  <div className="container mt-4">
                    <div className="row">
                       {items.map(item => <Product key={item.id} product={item} addItem={this.addItem} />)}
                    </div>
                  </div>
                </div>
              )
            }}
          </Query>
      )
   };
};

export default Products;
```

Update your `Navbar.js` with the following code:

```jsx
// src/components/Navbar.js
    import React from 'react';
    
    const Navbar = (props) => {
      return (
        <nav className="navbar navbar-light bg-light">
          <h3>Shoppr</h3>
            <button className="btn btn-outline-success my-2 my-sm-0" onClick={() => props.show()}>Cart {(props.cart.length)}</button>
        </nav>
      );
    };
    
    export default Navbar;
```

Now, create a `Cart.js` file and add the following code to it:

```jsx
import React from 'react';


const Cart = ({ handleClose, show, items }) => {

  return (
    <div className={show ? "modal display-block" : "modal display-none"}>
      <section className="modal-main">
        {items.map(item =>
           <div className="card" style={{width: "18rem"}}>
              <img src={item.image.downloadUrl} className="card-img-top" alt="shirt"/>
              <div className="card-body">
                <h5 className="card-title">{item.name}</h5>
                <h6 className="card-title">$ {item.price}</h6>
              </div>
            </div>
        )}
         Total items: {items.length}
        <button className="btn btn-warning ml-2" onClick={handleClose}>close</button>
      </section>
    </div>
  );

};

export default Cart;
```

We need a bit of styling to display our cart modal properly. Open up your `app.css` and add the following code to it:

```jsx
.modal {
  position: fixed;
  top: 0;
  left: 0;
  width:100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.6);
}

.modal-main {
  position:fixed;
  background: white;
  width: 80%;
  height: auto;
  top:50%;
  left:50%;
  padding: 10px;
  transform: translate(-50%,-50%);
}

.display-block {
  display: block;
}

.display-none {
  display: none;
}
```

Now open your shopping cart add items to it and view it via the cart button:

![shirts on an ecommerce site](https://blog.logrocket.com/wp-content/uploads/2019/12/shirts-ecommerce-nocdn.png.gif)

### Conclusion

In this tutorial, we have created a basic e-commerce store. The concepts learned here can help you create powerful e-commerce websites without worrying about your backend infrastructure. You can learn more about React [here](https://reactjs.org) and 8base [here](https://8base.com). You can find the code used in this tutorial [here](https://github.com/samuelayo/8base_shopping_cart).

Happy coding.

* * * 
**Editor's note:** Seeing something wrong with this post? You can find the correct version [here](https://blog.logrocket.com/building-an-e-commerce-website-with-react-and-8base/).

## Plug: [LogRocket](https://logrocket.com/signup/), a DVR for web apps
 
![LogRocket Dashboard Free Trial Banner](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png?resize=1200%2C677&ssl=1)
 
[LogRocket](https://logrocket.com/signup/) is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
 
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.
 
[Try it for free](https://logrocket.com/signup/).
* * *
The post [Building an e-commerce website with React and 8base](https://blog.logrocket.com/building-an-e-commerce-website-with-react-and-8base/) appeared first on [LogRocket Blog](https://blog.logrocket.com).