Create a product listing with Next.js - Part 2

by Jaeriah Tay on December 1, 2020
See live demo

In this section, you will make your first request to the Chec API using Commerce.js and build out the product listing page.

Create an index page

First create the directory /pages with index.js in it and type in the following:

const Index = () => <div>Hello</div>

export default Index;

Next.js comes with built-in page based and file system routing so any file in the pages directory is associated as a route. The file name computes to the route name. We will be creating dynamic routes in the next section but for now let's continue on with getting some data from the Chec API.

Fetch data from the Chec API

Commerce.js was built with all the frontend functionality needed to build a complete and custom eCommerce store. Simply make requests to various Chec API endpoints, receive successful responses, then use the raw data to output beautifully onto your web store.

Let's start to make requests to fetch data from Chec to list the merchant details and product data. Continuing from index.js, you need to first import in the commerce client created in lib then use the getStaticProps function in Next.js to store fetch and return our props. The two requests we will make are:

  • Make a request to the merchant API endpoint and fetch the merchant's information using the Commerce.js merchant.about method. This function returns the merchant object with details such as the name and contact info.
  • Make a request to the products API endpoint using the Commerce.js products.list method to fetch the products data. The request will return an array of product objects with properties such the products' names, prices, and description.

After the request statements, return both merchant and products and props. With the props now available, create the Index function, pass in both props and let's just render out the data in JSON to take a look at what gets returned!

import { commerce } from '../lib/commerce'

export async function getStaticProps() {
  const merchant = await commerce.merchants.about();
  const { data: products } = await commerce.products.list();

  return {
    props: {
      merchant,
      products,
    },
  }
}

const Index = ({ merchant, products }) => (
  <div>
    <h1>Merchant</h1>
    <pre>{JSON.stringify(merchant, null, 2)}</pre>
    <h1>Products</h1>
    <pre>{JSON.stringify(products, null, 2)}</pre>
  </div>
);

export default Index;

With the product data you will be able to use the various product properties such as product.name to render a product item component, which you'll get to building in the next section.

Create a product item component

The nature of modern frameworks is to separate your code into components.

Components are a way to encapsulate a group of elements for reuse throughout your application. You'll be creating two components for the product listing page, one will be for the single product item and another to render out the list of products.

Start by creating a function component and name it ProductItem.js in a new directory components. This component will render the individual product card. Pass in a product prop as the parameter. You will reference this property to access each product's image and name via product.media.source and product.name.

import ArrowRight from '../assets/arrow-right.svg';

const ProductItem = ({ product }) => {

    return (
        <div className="product">
            <img
                className="product__image"
                src={product.media.source}
                alt={product.name}
            />
            <div className="product__info">
                <h2 className="product__name">Shop {product.name}</h2>
                <ArrowRight className="product__icon" width={48} height={48} />
            </div>
        </div> 
    );
};

export default ProductItem;

With our ProductItem component, let's now get to creating a product listing component to render out a list of the product item cards in the next section.

Create a product listing page

It's now time to create a ProductsList.js component inside /components. The ProductsList component will be function component which will loop through and render a list of ProductItem components.

First, import the next/link module and the ProductItem component. Next, define a products prop. This will be provided by the parent component. You need to then use map through the products data array to render a ProductItem component for each product in your products prop. When a looping method is used to render out an array list, a unique identifier needs to be used (product.id) as the key attribute in the Link component - React will use it to determine which items in a list have changed and which parts of your application need to be re-rendered. The Link component wraps around each ProductItem to navigate to a single product detail page using the permalink property, you will be building this page view in the next section.

import Link from 'next/link';
import ProductItem from './ProductItem';

const ProductListing = ({ products }) => (
  <div className="products" id="products">
      {products.map((product) => (
          <Link href={`/product/${product.permalink}`} key={product.id}>
              <a>
                <ProductItem
                  product={product}
             />
           </a>
        </Link>
      ))}
  </div>
);

export default ProductListing;

Render the product listing page

With both your product item and list components created, let's get back to your Index.js to render the <ProductListing /> and pass in the products prop with the returned product data as the value.

import { commerce } from '../lib/commerce'
import Header from '../components/Header';
import Hero from '../components/Hero';
import ProductListing from '../components/ProductListing';

export async function getStaticProps() {
  const merchant = await commerce.merchants.about();
  const { data: products } = await commerce.products.list();

  return {
    props: {
      merchant,
      products,
    },
  }
}

const Index = ({ merchant, products }) => (
  <div>
    <Header merchant={merchant}/>
    <Hero />
    <ProductListing products={products} />
  </div>
);

export default Index;
#nextjs

About the author, Jaeriah Tay

Having been in communications design and entrepreneurship before joining Commerce.js, Jaeriah now contributes to both development and design and is passionate about both aspects of product.