How to Build a React E-Commerce Web App [Live Demo & Tutorial]

In a rush? Jump to the technical tutorial or live demo

The global pandemic fast-tracked the omnipresence of e-commerce in our lives.

It’s changing the way we purchase goods and services that we use at a pace that would have been hard to imagine not so long ago.

From buying some swag from our favorite tech companies to fulfilling a prescription, the web needs tools to provide a dynamic experience where consumers can easily find what they’re looking for and make the purchase.

In this post, I’ll explore how one of these tools, React, can help developers create these high-quality e-commerce experiences.

I won’t simply tell you that React can deliver dynamic UX; I’ll also show you by crafting a Next.js shop in a step-by-step tutorial:

  • Creating a new app with Next.js

  • Adding products to the React app

  • Integrating a shopping cart to our web app

  • Defining products within Snipcart

  • Setting up a cart summary and cart preview

We all want to build e-commerce projects that stand out. Let’s see how React can help.

Building a dynamic e-commerce experience

The crux of a shopping experience is being able to provide dynamic information to your site’s customers. This includes both the product information of what you’re trying to sell and how that relates to the actual customer.

The dynamic bits of products in e-commerce

When dealing with products, specifically physical goods, you might have a limited amount of products to sell. This means your shopping experience needs to be able to maintain an up-to-date count of how many items are left “in stock”.

Coupling that with the complexities of multiple people checking out simultaneously, you must be able to keep track of that quantity in real-time. Otherwise, you may run into situations where you end up overselling a product.

Pricing can also be a largely dynamic factor. Some may simplify it, where an item's price will always be a fixed amount, but you may find a use case where you want to change that price or provide a promotion to push your products.

The product page needs to reflect the cost that you ultimately charge the customer. While a cached price might be unintentional, you could quickly lose a customer's trust if they see a low price, only to end up being charged a different amount.

Providing a personalized e-commerce experience to customers

There are different levels of personalization we can provide customers who visit our website. Showing personalized product recommendations is a great way to help those visitors discover products they might not know exist.

But at a basic level, the core of any shopping experience that isn’t limited to a single product checkout flow is adding items to a shopping cart and allowing the customers to manage that cart.

The shopping cart can include how many products someone wants to purchase, which products they wish to purchase, the total cost of all of those items, and the shipping cost depending on the address provided.

These details, along with the product information, all lend themselves to providing a highly dynamic experience to help your customers through their checkout journey.

Is React Good for e-commerce?

React is a great JavaScript framework to build an e-commerce web app. It has a big & active community, is component-based, supports server-side rendering, uses virtual DOM, just to mention a few. These features make React.js the perfect choice for a fast, scalable, and user-friendly e-commerce website.

E-commerce website in the world of React

Technology stacks in the e-commerce world are more traditionally server-backed. Given the highly dynamic nature, developers need to ensure that the personalized information is accurately provided to the customer on each page load.

Dynamic experiences in React

In the world of React, typical solutions involve serving a static application to a browser and hydrating it with client-side requests to provide a dynamic experience.

Unknowingly to the visitor, the app for a split second will be unpersonalized or even blank. Once the JavaScript and subsequent server requests load, the page will be updated with any dynamic information needed.

Similar to a traditional “serverful” solution, server-side rendering (SSR) is also an option with React, but you lose the benefits of serving a static app straight from storage with a CDN in front of it.

Building fast, scalable e-commerce websites

Providing a resilient web app should be a critical part of any solution, but it’s even more critical in e-commerce.

Making sure your web app is available and functional has real currency attached to it, and those are real dollars lost to downtime if someone can’t browse your product offerings or purchase those products.

This is what’s given rise to the Jamstack , which brings dynamic features along with the benefits of a static app.

Benefiting from e-commerce on the Jamstack

We can provide that first byte to the browser statically from a CDN, which gives us tremendous benefits like fast page loads, infinite scalability, and a low hosting bill.

Example of how a CDN distributes requests

Each second—each millisecond—counts when serving an e-commerce app. Conversion rate is highly correlated to the amount of time it takes for a page to load in someone’s browser.

It’s also important to be able to scale up your store to the masses. You don’t want your product page down when your new collection goes viral, and that’s lost money and a lost customer that may not return because of their poor shopping experience.

SEO is crucial for an e-commerce website. Learn about React SEO for e-commerce with this guide.

Leveraging React with e-commerce

And this is where React comes into play. React is a powerful library that gives us the ability to create dynamic experiences in the browser.

We can serve a completely static page to the browser and then load in the dynamic parts with those same client-side requests to provide real-time product data and a personalized shopping experience.

Loading and updating dynamic content in the browser

This becomes even easier with frameworks like Next.js and Gatsby. Both tools allow developers to statically compile the entire application, providing the majority of a page’s content with that first request, but then layer in anything that needs to be critically accurate.

For instance, most details of a product probably won’t change. Sure, we might update the copy and fix errors, but those aren’t critical to a real-time shopping experience.

We can statically compile those details to use tools like content management systems (CMS) that store that information. We would then pull that information into a framework like Next.js to display. If those details change, we can trigger a new build that will go out and fetch the latest information to show on our page.

For serving the dynamic details, like an up-to-date product price or an accurate tax calculation, we can make client-side requests to APIs that will ensure that we’re always showing the right value. With this, we’re leveraging the best of both worlds, providing a fast experience with real-time, dynamic details.

Creating a React e-commerce website with Next.js and Snipcart

Now that we understand the benefits of building e-commerce stores with React, let’s get into how we can craft them.

We’re going to use Next.js to rapidly spin up a new React application where we can manage and display our products.

I also mentioned Gatsby earlier, remember? Well, the Snipcart team recently crafted an e-commerce recipe for this alternative React framework. You can read about it here.

We’ll then layer in Snipcart, which will provide our shopping cart experience, allowing us to provide a way for people to purchase our products.

Prerequisites

Before getting started, we’ll assume that you’ve already created a free Snipcart account. If you don’t have an account, you can sign up here. It’s forever free in Test mode.

You’ll also need a basic understanding of JavaScript and React. While most of what you’ll do includes plain HTML, we’ll be working within a React application using Next.js.

Step 0: Creating a new React app with Next.js

We’ll be using Next.js to create our React app. To do that, we can use npm to create a new app with the default Next.js template quickly.

First, navigate to the directory in your terminal that you want to create your new app in and run:

npx create-next-app next-snipcart-store

You can optionally replace next-snipcart-store with the name of the directory you want to create this project in.

This will create a new Next.js project and install the dependencies. Once it’s finished, you can navigate to that directory and run the development command to start the server.

cd next-snipcart-store
npm run dev

Creating a new Next.js app

And once it’s finished, you can now open up the project at http://localhost:3000.

Step 1: Adding products to our new React app

To get started adding our products to the app, we first need a list of products.

Let’s create a new file at the root of our project to store that product info that we can use throughout the app.

Create a new file called products.json and inside that file, simply add an empty array:

[]

When setting up our products, we need a few basic attributes:

  • Title: the human-friendly name of the product

  • ID: a unique identifier for that product

  • Description: a brief note about what the product is

  • Price: the cost of the item

We can create our first product by adding a new object inside of our empty array with the following:

{
  "title": "Snipcart Logo Sticker",
  "id": "sticker_logo",
  "description": "Show off your Snipcart support with a logo sticker!",
  "price": "2.00"
}

Here’s a code snippet of what our file should look like at this point:

To use that file, we can go to our homepage file and import it.

In your code editor, open up the pages/index.js file and add the following import statement at the top of the file:

import products from '../products.json';

With our products imported, we can now use them to display on the page.

Inside of <div className={styles.grid}>, Next.js includes some default links about Next.js. We’re going to remove these and replace them with our own links.

Replace the grid with the following:

<div className={styles.grid}>
  {products.map(product => {
    return (
      <div key={product.id} className={styles.card}>
        <h3>{ product.title }</h3>
        <p>{ product.description }</p>
        <p>${ product.price }</p>
        <p>
          <button>Add to Cart</button>
        </p>
      </div>
    );
  })}
</div>

Here, we’re looping through the array of products that we imported. We’re creating a new <div> for each product that includes a className that borrows the Next.js default styles for a card.

Inside of our <div>, we’re including details about our product like the title and price, as well as adding an HTML button that we can use to add the item to our shopping cart.

If we save the file and open up our browser, we can now see our first product.

Let’s add a second product.

We can add another object to our project array for our second product:

{
  "title": "Snipcart Logo Sticker Pack",
  "id": "sticker_logo_pack",
  "description": "Get a pack of 3 Snipcart logo stickers.",
  "price": "4.00"
}

And if we save and reload our page, we see our second product.

Finally, typically when we want to sell a product, we want to show an image of those products so our customers can see what the product looks like.

Let’s add two image files to our project. Under the public directory, create a folder called “images”, and add your image files there, one for each product.

I included two images, one for a single sticker and one for a pack of stickers.

Note: if you want to use the same image files, you can download them from the

Git repository with this demo.

Inside of our products.json file, we now want to add those image files so we can grab them in our app.

Under “Snipcart Logo Sticker”, add the following property:

"image": "/images/sticker-single.jpg"

And under “Snipcart Logo Sticker Pack”, add:

"image": "/images/sticker-3pack.jpg"

Then, back inside pages/index.js, above our product title, add:

<img src={product.image} alt={`Preview of ${product.title}`} />

And if we save and reload the page, we see we have our images, but they’re huge!

To fix the image sizes, you can open up styles/global.css and add the following rule:

img {
  max-width: 100%;
}

And now we have our page with our two products!

Step 2: Adding a Snipcart shopping cart to our React app

The first part of integrating Snipcart includes importing a few files from the Snipcart public CDN.

Inside of pages/index.js, the default Next.js template comes with a <Head> component that allows us to add additional tags and scripts to the <head> of our page.

Inside of the component, add the following:

<link rel="preconnect" href="https://app.snipcart.com" />
<link rel="preconnect" href="https://cdn.snipcart.com" />
<link rel="stylesheet" href="https://cdn.snipcart.com/themes/v3.2.2/default/snipcart.css" />

This is going to tell the browser to start a connection to the two of Snipcart’s subdomains, which will help with performance. We’re also including a CSS file that contains the Snipcart styles for the shopping cart.

Next, as the bottom of the file, right after the <footer>, add the following:

<script async src="https://cdn.snipcart.com/themes/v3.2.2/default/snipcart.js" />
<div hidden id="snipcart" data-api-key="[YOUR-API-KEY]" />

Here, we’re including the Snipcart script that will provide all of our shopping cart's functionality. We’re also including a hidden <div> where we need to specify our API key from our account.

To find the API key, inside your Snipcart account, navigate to your account settings, find the API Keys page, and copy the Public Test API Key under Credentials.

Copy that value and replace [YOUR-API-KEY] in the snippet above with your key:

<div hidden id="snipcart" data-api-key="123456789012345678901234567890" />

At this point, if we save and reload the page, we shouldn’t notice any difference.

Step 3: Setting up the products to add to the Snipcart shopping cart

In order to let people add our products to their user-friendly shopping cart, we need to add a few attributes to our product buttons.

Let’s update our Add to Cart button to the following:

<button className="snipcart-add-item"
  data-item-id={product.id}
  data-item-image={product.image}
  data-item-name={product.title}
  data-item-price={product.price}
>
  Add to Cart
</button>

With these attributes, Snipcart can dynamically look at our products and be able to find out the details about each of them. Additionally, because we’re adding the class selector, Snipcart can now transform our buttons into working buttons allowing us to actually add our items to the shopping cart.

As we can see, Snipcart knows exactly what product we added to our cart by looking at the attributes on our button!

Similar to how we set up our products to easily add them to our Snipcart shopping cart, we can create a link that lets our customers visit that cart page. We can also show an up-to-date total cost so that our customers always know how much they’re looking to spend.

To do this, we’re going to take advantage of the existing description on the page inside of <p className={styles.description}>.

Let's update our Nav component with the following:

import Link from "next/link";
import { useEffect, useState } from "react";
​
import { FaShoppingCart } from "react-icons/fa";
​
import Container from "../Container";
​
import styles from "./Nav.module.css";
​
const Nav = ({ children }) => {
  const [total, setTotal] = useState(0);
  useEffect(() => {
    if (window.Snipcart) {
      setTotal(Snipcart.store.getState().cart.total);
    }
  });
  
  return (
    <nav className={styles.nav}>
      <Container className={styles.navContainer}>
        <p className={styles.title}>
          <Link href="/">
            <a>Snipcart Store</a>
          </Link>
        </p>
        <p className={styles.description}>
          <a
            className="snipcart-checkout snipcart-summary"
            href="#"
            style={{ textDecoration: "none" }}
          >
            <FaShoppingCart />
            <strong className="sr-only">Cart</strong>
            <span className="snipcart-total-price">
              {new Intl.NumberFormat("en-US", {
                style: "currency",
                currency: "USD",
              }).format(total)}
            </span>
          </a>
        </p>
      </Container>
    </nav>
  );
};
​
export default Nav;

First, we’re adding a new link, including class selectors, that will tell Snipcart that we want to use our link as a container for our cart summary. We’re also telling it that we want this link to open up our shopping cart.

Inside, we’re adding an icon of a “Cart”.

Next, we include a separate <span> with its own class selectors that will let Snipcart initially update that value with the current total of our customer’s cart.

If you notice, we’re setting a default value of 0 to our total and formatting it using the browser's native NumberFormat method. This will allow our page to show a value before the JavaScript loads to avoid layout shifts when possible.

We also update the total programmatically every time the component re-rerenders (using the useEffect method) by retrieving the value directly from the SDK`s store. This will ensure we always get an updated value when the route of the application changes.

Finally, while we’re here, let’s update the page’s title inside of the <h1> tag to something that reflects our store.

I’m going to update it to “Snipcart Store”:

<h1 className={styles.title}>
  Snipcart Store
</h1>

If we refresh the page, we can see our updated title. But if we add one of the products to the cart and close the shopping cart, we can see our cart's updated total cost. We can even click on our Cart link, which will open back up our cart!

Next Steps

Hosting and deploying your store

There are a variety of options available for hosting and deploying your Next.js app. Vercel, the team that maintains Next.js, comes with a lot of functionality “out of the box” that allows you to host and deploy a Next.js app easily.

If you plan on going with another static provider, such as Netlify, you’ll want to configure the project’s build script to export the compiled app as static files. To do this, you can update your build script inside of package.json to be:

"build": "next build && next export",

Now, whenever a build is run, you will have static files available in the out directory.

Setting up and managing your products

If you followed along, you might have used the sample products from the demo. At this point, you can update the products inside products.json to include the products your store is actually offering. You can ingest the product information from an external source like a custom CM for a more advanced solution!

Customizing your store

For this walkthrough, we took advantage of pretty much all of the styles already built into the default Next.js template. This might not look exactly like your brand or how you imagine your store.

With Next.js, we can use most CSS solutions, including standard CSS, to customize our page how we want it, whether it’s merely updating the buttons to look a little nicer or completely rebranding the store.

Taking your React e-commerce website live

We used a test API key to make sure our shopping cart worked as expected in our setup. This allows us actually to process transactions like we would in the real world.

First, you’ll need to make sure you have payments set up with your Snipcart account to take your store live.

Once you’re ready to go, you can update your account into Live mode, which will allow you to start selling your products to the world!

Live demo & GitHub repo

Try out the live demo here

See the GitHub repo here

Closing Thoughts

E-commerce is a complicated space, requiring highly dynamic content that will scale to our stores' customers.

With React and Next.js, we can provide a static app that will be able to survive large influxes of traffic when a product goes viral, all while being able to provide an interactive experience for people to buy our products.

Using Snipcart, we can confidently provide a shopping experience tailored to our product offering that’s personalized to each customer. Snipcart lets us handle the entire checkout flow all in the browser allowing people to quickly and securely make a payment.

We can bring the dynamic experiences needed in the e-commerce world to the static web by leveraging these tools.

About the author

Colby Fayock
Senior Developer Experience Engineer at Cloudinary

Learning by doing is the best way to learn, and it’s how Colby Fayock helps others learn Javascript, React, and the static web. His work includes technical writing, videos on YouTube, courses on egghead.io, two books including Jamstack Handbook, and a Senior Developer Experience Engineer at Cloudinary.

Follow him on Twitter!

New to Jamstack? Everything You Need to Know to Get Started

Read next from Colby
View more

36 000+ geeks are getting our monthly newsletter: join them!