Jalan Technologies > Blog >

Create your own eCommerce website with React

Create your eCommerce website with React and Shopify. This step-by-step guide helps you set up your online store quickly and offers the flexibility to customize it according to your needs. Get started with your own eCommerce venture today!

React is loved for its speed and component-based structure. Due to this, it is widely used in eCommerce stores where performance is the topmost priority. In this article, we will see how you can create your own simple eCommerce website with React js and Shopify.

Create your own eCommerce website with React

Getting started
Before writing the code, we have to setup the project and install some dependencies. To create a new react project, enter the following command in the terminal.

npx create-react-app shopify-react

After the project is installed, paste the following dependencies in package.json.

"dependencies": {
   "@material-ui/core": "^4.9.0",
   "@testing-library/jest-dom": "^4.2.4",
   "@testing-library/react": "^9.3.2",
   "@testing-library/user-event": "^7.1.2",
   "atomize": "^1.0.20",
   "react": "^16.12.0",
   "react-dom": "^16.12.0",
   "react-router-dom": "^5.1.2",
   "react-scripts": "3.3.1",
   "react-transition-group": "^4.3.0",
   "shopify-buy": "^2.9.0",
   "styletron-engine-atomic": "^1.4.4",
   "styletron-react": "^5.2.6"
 },

Now run yarn install to install these packages in your local machine.

Writing the code
Now that we have all the desired packages installed in our personal machine, let us create the following folders in /src directory.

Ecommerce website with react

 

The most important thing is our shop data that will be rendered inside the components. Let us create a shop context. Create a new file shopContext.js in /src/context and enter the following code inside it.

import React, { Component } from "react";
import Client from "shopify-buy";
 
const ShopContext = React.createContext();
 
const client = Client.buildClient({
 storefrontAccessToken: "key", // your key goes here
 domain: "abc.myshopify.com", //your token goes here.
});
 
class ShopProvider extends Component {
 state = {
   products: [],
   product: {},
   checkout: {},
   isCartOpen: false,
   };
 
 componentDidMount() {
 
   if (localStorage.checkout) {
     this.fetchCheckout(localStorage.checkout);
   } else {
     this.createCheckout();
   }
 
 }
 
 createCheckout = async () => {
   const checkout = await client.checkout.create();
   localStorage.setItem("checkout", checkout.id);
   await this.setState({ checkout: checkout });
 };
 
 fetchCheckout = async (checkoutId) => {
   client.checkout
     .fetch(checkoutId)
     .then((checkout) => {
       this.setState({ checkout: checkout });
     })
     .catch((err) => console.log(err));
 };
 
 addItemToCheckout = async (variantId, quantity) => {
   const lineItemsToAdd = [
     {
       variantId,
       quantity: parseInt(quantity, 10),
     },
   ];
   const checkout = await client.checkout.addLineItems(
     this.state.checkout.id,
     lineItemsToAdd
   );
this.setState({ checkout: checkout });
   console.log(checkout);
 
   this.openCart();
 };
 
 fetchAllProducts = async () => {
   const products = await client.product.fetchAll();
   this.setState({ products: products });
 };
 
 fetchProductWithId = async (id) => {
   const product = await client.product.fetch(id);
   this.setState({ product: product });
   console.log(JSON.stringify(product));
 
   return product;
 };
 
 closeCart = () => {
   this.setState({ isCartOpen: false });
 };
 openCart = () => {
   this.setState({ isCartOpen: true });
 };
 
 render() {
   return (
     <ShopContext.Provider
       value={{
         ...this.state,
         fetchAllProducts: this.fetchAllProducts,
         fetchProductWithId: this.fetchProductWithId,
         closeCart: this.closeCart,
         openCart: this.openCart,
         addItemToCheckout: this.addItemToCheckout,
       }}
     >
     {this.props.children}
     </ShopContext.Provider>
   );
 }
}
 
const ShopConsumer = ShopContext.Consumer;
 
export { ShopConsumer, ShopContext };
 
export default ShopProvider;

Here, we have created a global context provider that will be holding the state for our products and cart. We will wrap our whole application with ShopProvider. Other than this, we are using built-in functions to get cart that are provided by shopify library.

Now, let us create our HomePage.js and ProductPage.js in pages folder

Product.js

import React, { useEffect, useContext } from 'react'
import { useParams } from 'react-router-dom'
import { ShopContext } from '../context/shopContext'
import { Text, Div, Button, Row, Col, Container } from 'atomize'
import Loading from '../components/Loading'
 
const ProductPage = () => {
   let { id } = useParams()
   const { fetchProductWithId, addItemToCheckout, product } = useContext(ShopContext)
 
   useEffect(() => {
       fetchProductWithId(id)
      
       // fetchData()
       return () => {
           // setProduct(null)
       };
   }, [ fetchProductWithId, id])
 
   if (!product.title) return <Loading />
   return (
       <Container>
           <Row m={{ b: "2rem" }} p="2rem">
               <Col>
                   <Div bgImg={product.images[0].src} shadow="3" bgSize="cover" w="100%" bgPos="center center" h="40rem"/>
               </Col>
               <Col>
                   <Text tag="h1" textColor="black500" textWeight="200" m={{ y: '2rem' }}>{product.title}</Text>
                   <Text tag="h3" m={{ y: '2rem' }} textWeight="200">${product.variants[0].price}</Text>
                   <Text tag="p" textSize="paragraph" textColor="gray900" textWeight="200">{product.description}</Text>
                   <Button rounded="0" shadow="3" bg="black500" m={{ y: '2rem' }} onClick={() => addItemToCheckout(product.variants[0].id, 1)}>Add To Cart</Button>
               </Col>
           </Row>
       </Container>
   )
}
 
export default ProductPage

HomePage.js

import React, { useContext, useEffect }  from 'react'
import { ShopContext } from '../context/shopContext'
import { Text, Div, Row, Col, Container } from "atomize";
import { Link } from 'react-router-dom'
import Loading from '../components/Loading'
const HomePage = () => {
   const {fetchAllProducts, products} = useContext(ShopContext)
 
   useEffect(() => {
       fetchAllProducts()
       return () => {
           // cleanup
       };
   }, [fetchAllProducts])
 
   if (!products) return <Loading />
   return (
       <Container>
           <Row>
               {products.map(product => (
                   <Col key={product.id} size="3" >
                       <Link to={`/product/${product.id}`} style={{ textDecoration: 'none' }}>
                           <Div p="2rem">
                               <Div
                                   h="20rem"
                                   bgImg={product.images[0].src}
                                   bgSize="cover"
                                   bgPos="center center"
                                   shadow="3"
                                   hoverShadow="4"
                                   transition="0.3s"
                                   m={{ b: "1.5rem" }}
                                   >
                               </Div>
                               <Text tag="h1" textWeight="300" textSize="subheader" textDecor="none" textColor="black500">{product.title}</Text>
                               <Text tag="h2" textWeight="300" textSize="body" textDecor="none" textColor="gray500">${product.variants[0].price}</Text>
                           </Div>
                       </Link>
                       </Col>
               ))}
           </Row>
       </Container>
   )
}
 
export default HomePage

In both of the pages, we are getting the data from context and rendering it on the frontend by using the map(). We have completed the major part of our store, we are left with smaller components that are used in these pages.
Let us create Loading.js, Cart.js and Navbar.js in the components folder.

Navbar.js

import React, {useContext} from 'react'
import { Container, Anchor, Icon } from 'atomize'
import { Link } from 'react-router-dom'
import { ShopContext } from '../context/shopContext'
 
const Navbar = () => {
 
   const { openCart } = useContext(ShopContext)
 
   return (
       <> 
           <Container d="flex" flexDir="row" p="2rem" justify="space-between" >
               <Link to="/"><Icon name="Store" size="30px" color="black500" /></Link>
               <Anchor onClick={() => openCart()}><Icon name="Bag" size="20px" color="black500" /></Anchor>
           </Container>
       </>
   )
}
 
export default Navbar

Loading.js

import React from "react";
import { Div, Icon } from "atomize";
 
const Loading = () => {
 return (
   <Div
     bg="transparent"
     d="flex"
     align="center"
     justify="center"
     pos="absolute"
     top="0"
     bottom="0"
     right="0"
     left="0"
     style={{ zIndex: -1 }}
   >
     <Icon name="Loading3" size="4rem" color="brand500" />
   </Div>
 );
};
 
 
export default Loading;

Checkout.js

import React, { useContext } from 'react'
import { Div, SideDrawer, Text, Row, Col, Anchor, Button, Container, Icon } from "atomize";
import {ShopContext} from '../context/shopContext'
 
const Cart = () => {
 
   const { isCartOpen, closeCart, checkout } = useContext(ShopContext)
 
   if (checkout.lineItems) {
       return (
           <SideDrawer isOpen={isCartOpen} onClose={closeCart}>
               <Container d="flex" flexDir="column" h="100%">
                   <Row justify="space-between" border={{ b: '1px solid' }} p="0.7rem" borderColor="gray300">
                       <Text tag="h1" textColor="black500" textSize="paragraph" hoverTextColor="black700" transition="0.3s">Bag</Text>
                       <Anchor onClick={() => closeCart()} ><Icon name="Cross" color="black500"/></Anchor>
                   </Row>
                   <Row flexGrow="2" p="0.7rem" overflow="auto" flexWrap="nowrap" flexDir="column">
                       {checkout.lineItems.length < 1 ?
                           <Row>
                               <Col><Text tag="h1" textColor="black500" textSize="paragraph" hoverTextColor="black700" transition="0.3s">Cart Is Empty</Text></Col>
                           </Row>
                           :
                           <>
                               {checkout.lineItems && checkout.lineItems.map(item => (
                                   <Row key={item.id} p={{ t:"5px" }}>
                                       <Col>
                                           <Div bgImg={item.variant.image.src} bgSize="cover" bgPos="center" h="5rem" w="4rem"/>
                                       </Col>
                                       <Col>
                                                         <Text>{item.title}</Text>
                                           <Text>{item.variant.title}</Text>
                                           <Text>{item.quantity}</Text>
                                       </Col>
                                       <Col>
                                           <Text>{item.variant.price}</Text>
                                       </Col>
                                   </Row>
                               ))}
                           </>
                       }
                   </Row>
                   <Row border={{ t: '1px solid' }} p="0.7rem" borderColor="gray300">
                       <Anchor w="100%" href={checkout.webUrl} target="_blank" rel="noopener noreferrer">
                           <Button w="100%" rounded="0" bg="black500" shadow="2" hoverShadow="3" m={{t: '1rem'}}>
                               Checkout
                           </Button>
                       </Anchor>
                   </Row>
               </Container>
           </SideDrawer>
       )
   }
 
   return null
 
}
 
export default Cart

The cart object is returned by shopify in the context and we use it to map items for the frontend. Finally, we import all of these files and use it in our App.js

import React from 'react';
import './App.css';
import { Provider as StyletronProvider, DebugEngine } from "styletron-react";
import { Client as Styletron } from "styletron-engine-atomic";
import { BrowserRouter as Router, Switch, Route, } from "react-router-dom";
import ShopProvider from './context/shopContext'
 
import HomePage from './pages/HomePage'
import ProductPage from './pages/ProductPage'
import Navbar from './components/Navbar'
import Cart from './components/Cart'
 
const debug = process.env.NODE_ENV === "production" ? void 0 : new DebugEngine();
const engine = new Styletron();
 
 
const App = () => {
 return (
   <ShopProvider>
     <StyletronProvider value={engine} debug={debug} debugAfterHydration>
       <Router>
         <Navbar />
         <Cart />
         <Switch>
           <Route path="/product/:id">
             <ProductPage />
           </Route>
           <Route path="/">
             <HomePage />
           </Route>
         </Switch>
       </Router>
     </StyletronProvider>
   </ShopProvider>
 );
}
 
export default App;

Here, we have two main routes for our pages that are dynamic based on their ids. For styling purposes, we have wrapped the components with the StyletronProvider which is our style engine for the project. And at the end, the whole app is wrapped by the ShopProvider for accessing the global state.

Let us run the project with the following command and see the result.

yarn start

Homepage

image3

image4

image2

Clicking on checkout will lead to a payment page on Shopify. Your Ecommerce Website with shopify has been created

In this article, we have seen how we can create your own eCommerce website with react and Shopify in a few steps. The whole process is really simple and you are free to add as much customization as you like. We hope this tutorial must have provided you with enough knowledge to start your own Ecommerce stores.

What’s the biggest thing you’re struggling with right now that we as a technology consulting company can help you with? Feel free to reach out to Jalan Technologies. We hope our assistance will help!

Disclaimer: The statements and opinions expressed in this article are those of the author(s) and do not necessarily reflect the positions of Jalan Technologies.

Table of Contents

Hire Our Development Experts.




    Want to raise the bar for your organization?

    Subscribe to our newsletter to receive latest insights on how technology can help turn your goals into reality. By subscribing, you’ll get access to thought-provoking articles, case studies, and resources to help accelerate your impact.

    Get the latest updates straight to your inbox

      Related Blogs
      technology consultant
      Business Insights
      All you need to know about technology consultant

      Technology consultant experts like Jalan Technologies, empowers businesses to strategically leverage technology for success. Services encompass strategic planning, system integration,

      Scroll to Top

      Subscribe Now

        Never Miss Another Post