Part 38: Fetching Product Data in Next.js: Client-Side Rendering Approach

[Pages] Data Fetching

[Pages] Data Fetching

In the previous post, we explored server-side rendering using getStaticProps to fetch product data in a Next.js application. Now, let's dive into the client-side rendering approach. This method fetches data in the browser, allowing for dynamic updates and the display of the latest content from a CMS.

Implementing Client-Side Data Fetching

In this approach, we'll fetch product data when the component is mounted on the client side. This is akin to how data is typically fetched in a classic React app.

Step 1: Set Up the State and Effect Hooks

We'll begin by loading our index-2 page, which initially displays hard-coded products. Our goal is to replace these with data fetched from the CMS.

// pages/index-2.js

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

function HomePage() {
  const [products, setProducts] = useState([]);
  
  useEffect(() => {
    getProducts().then(setProducts);
  }, []);

  console.log('[HomePage] render:', products);
  return (
    <>
      <Head>
        <title>Next Shop - Client Side</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;

Step 2: Fetch Data with useEffect

We use the useState hook to create a state variable, products, initially set to an empty array. The useEffect hook then triggers a function when the component mounts, fetching the product data from the CMS.

  • useState([]): Initializes products as an empty array.

  • useEffect(() => { ... }, []): Runs the effect once, after the component mounts, to fetch the products.

The getProducts function, which we previously defined, returns a Promise. Instead of using await, we call .then() on the Promise to update the state with setProducts.

Step 3: Render the Product List

With the state updated, we render the list of products dynamically. As data is fetched, the component re-renders to display the updated list.

Comparing Client-Side and Server-Side Rendering

Both client-side and server-side approaches have their merits, and understanding their differences helps in choosing the right one for your application.

Client-Side Rendering Characteristics

  • Dynamic Updates: Fetching data in the browser ensures that users always see the latest data available from the CMS.

  • Public API Access: The CMS API needs to be publicly accessible since the browser makes direct requests.

  • Initial Render: The page initially renders with an empty product list, which updates once the data is fetched.

Server-Side Rendering Characteristics

  • Pre-rendered HTML: Pages are pre-rendered with data at build time, resulting in faster initial load times and better SEO.

  • Private API Access: The CMS API only needs to be accessible to the server, reducing potential security risks.

  • Data Optimization: Allows for data filtering on the server, reducing the amount of data sent to the client.

Conclusion

Choosing between client-side and server-side data fetching depends on your application's requirements. Client-side rendering offers real-time data updates, ideal for applications where content changes frequently. On the other hand, server-side rendering provides performance and SEO benefits, making it suitable for static content.

In the next post, we'll delve into strategies for handling data updates in statically generated pages, ensuring your application remains up-to-date without sacrificing the benefits of server-side rendering. Stay tuned for more insights into optimizing your Next.js applications!

Last updated