Part 45: Building Dynamic Product Pages in Next.js: A Step-by-Step Guide

[Pages] Data Fetching

[Pages] Data Fetching

In our previous session, we discussed implementing a dynamic product page as an exercise. Now, let's walk through the process together. We'll create a page that fetches and displays individual product data using Next.js.

Setting Up the Product Page Component

First, let's establish a basic React component structure for our product page. This component will be the default export of our file. We will start by copying the structure from our HomePage, but we'll adjust it to suit a single product view.

Creating the Product Page Component

Here's how you can set up the initial component:

// pages/products/[id].js

import Head from 'next/head';
import Title from '../../components/Title';
import { getProduct, getProducts } from '../../lib/products';

function ProductPage({ product }) {
  return (
    <>
      <Head>
        <title>{product.title} - Next Shop</title>
      </Head>
      <main className="px-6 py-4">
        <Title>{product.title}</Title>
        <p>{product.description}</p>
      </main>
    </>
  );
}

export default ProductPage;

Explanation

  • React Component: The ProductPage component receives a product prop and renders the product's title and description.

  • Head Component: Utilized to set the HTML <title> dynamically based on the product title.

Implementing getStaticPaths and getStaticProps

To fetch and display different content for each product, we need to implement getStaticPaths and getStaticProps.

Setting Up getStaticPaths

This function determines which product pages need to be generated at build time.

// pages/products/[id].js (continued)

export async function getStaticPaths() {
  const products = await getProducts();
  return {
    paths: products.map((product) => ({
      params: { id: product.id.toString() },
    })),
    fallback: false,
  };
}

Explanation

  • Fetching Products: We use the getProducts function to retrieve all product data.

  • Paths Array: Maps over the products to create an array of path objects. Each path object contains a params object with an id property, which is converted to a string because URLs require string parameters.

Setting Up getStaticProps

This function fetches data for a specific product page.

// pages/products/[id].js (continued)

export async function getStaticProps({ params: { id } }) {
  const product = await getProduct(id);
  return {
    props: { product },
  };
}

Explanation

  • Fetching Single Product: The getProduct function fetches data for a specific product based on the id parameter.

  • Returning Props: The product data is returned as props, which are then available to the ProductPage component.

Enhancing the Data Layer

To support fetching a single product, we need to add a new function in our data layer.

Adding a Function to Fetch a Single Product

// lib/products.js

function stripProduct(product) {
  return {
    id: product.id,
    title: product.title,
    description: product.description,
  };
}

export async function getProduct(id) {
  const response = await fetch(`http://localhost:1337/products/${id}`);
  const product = await response.json();
  return stripProduct(product);
}

Explanation

  • stripProduct Function: Extracts only the necessary fields from the product data.

  • Fetching Single Product: The getProduct function constructs a URL using the product id to fetch data for a specific product.

Conclusion

By following these steps, we've successfully implemented dynamic product pages in our Next.js application. These pages efficiently fetch and display data for individual products, enhancing user experience by providing detailed information on each product. This setup not only streamlines our application but also lays the groundwork for further enhancements, such as adding more product details or integrating additional features. Keep experimenting, and happy coding!

Last updated