Part 36: Fetching Product Data in Next.js: A Tale of Two Approaches

[Pages] Data Fetching

[Pages] Data Fetching

In our journey to build a dynamic shop using Next.js, we've set up a local Strapi server populated with product data. We've also learned how to access this data via the REST API. Now, the challenge is fetching this product data from our Next.js application and displaying it on the frontend. This blog post will guide you through setting up the user interface and exploring two different approaches to fetching data: server-side and client-side.

Preparing the User Interface

Before diving into data fetching, let's set up a basic user interface to display our products. We'll start by using some dummy data to focus on the UI components.

Setting Up the Component

Create a simple component to render a list of products:

// pages/index.js

import Head from 'next/head';
import Title from '../components/Title';

const products = [
  { id: 1, title: 'First Product' },
  { id: 2, title: 'Second Product' },
];

function HomePage() {
  console.log('[HomePage] render:', products);
  return (
    <>
      <Head>
        <title>Next Shop</title>
      </Head>
      <main className="px-6 py-4">
        <Title>Next Shop</Title>
        <ul>
          {products.map((product) => (
            <li key={product.id}>
              {product.title}
            </li>
          ))}
        </ul>
      </main>
    </>
  );
}

export default HomePage;

This code snippet sets up a basic page that lists dummy products using an unordered list. Each product is displayed as a list item, and we use the product ID as a unique key for each item.

Fetching Product Data

With our UI prepared, we now need to replace the dummy data with actual product data fetched from the Strapi server. We have two main options for fetching data in Next.js: server-side and client-side.

Option 1: Server-Side Fetching

Server-side data fetching means retrieving data during the build process or on each request, depending on the method used. We'll use getStaticProps to fetch data at build time.

// pages/index-1.js

import Head from 'next/head';
import Title from '../components/Title';

export async function getStaticProps() {
  const res = await fetch('http://localhost:1337/products');
  const products = await res.json();

  return {
    props: {
      products,
    },
  };
}

function HomePage({ products }) {
  console.log('[HomePage] render:', products);
  return (
    <>
      <Head>
        <title>Next Shop</title>
      </Head>
      <main className="px-6 py-4">
        <Title>Next Shop</Title>
        <ul>
          {products.map((product) => (
            <li key={product.id}>
              {product.title}
            </li>
          ))}
        </ul>
      </main>
    </>
  );
}

export default HomePage;

In this approach, we define a getStaticProps function that fetches product data from the API. The data is then passed to the component as props, allowing us to render it on the server side.

Option 2: Client-Side Fetching

Client-side fetching involves making HTTP requests from the browser after the component mounts. This is typically done using the useEffect hook in React.

// pages/index-2.js

import { useState, useEffect } from 'react';
import Head from 'next/head';
import Title from '../components/Title';

function HomePage() {
  const [products, setProducts] = useState([]);

  useEffect(() => {
    async function fetchData() {
      const res = await fetch('http://localhost:1337/products');
      const data = await res.json();
      setProducts(data);
    }
    fetchData();
  }, []);

  console.log('[HomePage] render:', products);
  return (
    <>
      <Head>
        <title>Next Shop</title>
      </Head>
      <main className="px-6 py-4">
        <Title>Next Shop</Title>
        <ul>
          {products.map((product) => (
            <li key={product.id}>
              {product.title}
            </li>
          ))}
        </ul>
      </main>
    </>
  );
}

export default HomePage;

In this method, we use the useEffect hook to fetch data after the component mounts. The fetched data is stored in a state variable, which is then used to render the product list.

Comparing the Approaches

Each approach has its advantages:

  • Server-Side Fetching: Ensures that data is available when the page loads, which can improve performance and SEO. However, it may increase build time if the dataset is large.

  • Client-Side Fetching: Allows for more dynamic and interactive user experiences, as data can be refreshed without reloading the page. However, it may result in a brief loading state while data is being fetched.

By understanding and experimenting with both options, you can choose the best approach for your specific use case and performance requirements. As we continue developing our Next.js shop, these techniques will prove invaluable in creating a responsive and data-driven application.

Last updated