Data Fetching in Next.js

Data Fetching in Next.js

by Favour Ogbonda

Next.js is a perfect React framework that is fast, has more configuration, good image optimization features, and rendering capabilities. It also has methods that help in data fetching from the back end. This article will go through how data is fetched on the client-side, server-side, and static site generation. First, let us look at what data fetching is and how it is done in Next.js.

What is Data Fetching?

Data fetching is simply a way to get data. The data could be obtained from a database, JSON file, or another software through an API, and it can be done during client-side rendering, server-side rendering, or static site generation.

Fetching data from the server-side, client-side, or static-site generation could have some benefits:

  • Having access to the data coming from the backend.
  • It can cache your data by storing it in a particular location to reduce load time.
  • Ability to make multiple data fetches.

Data fetching features

In Next.js, there are some ways to get data. Data is either from the client-side, server-side, or static-site generation.

  • Client-side data fetching: In client-side data fetching, the data is fetched on the client, such as the browser, after the UI has been sent to the user, even when new data is added to the backend. This reduces Search Engine optimization because the UI is sent to the user without the layout markup(HTML tags such as <a>, <p>, <h1>, etc. ), and when the data is gotten, then the layout of the markup is made. Client-side data fetching in Next.js uses the useState and useEffect hooks from React to render data on the browser.

  • Server-side data fetching: In server-side data fetching, the data is fetched while the UI is still on the local machine before rendering it to the user. Every time data is added or updated, the UI asks for all the data again, which means that on every browser refresh, the data fetch again before rendering it to the user. The UI is created on the local machine due to frontend libraries and frameworks like React or Next.js, which we use to create the UI. Our local machine act as a server. Server-side data fetching in Next.js works using the getServerSideProps to fetch data from a database or an API as a backend.

  • Static-site generation: To go further, let us look at what static site generation is. In a static-site generation, let us assume you have a UI built on your local machine and an API or database as the backend containing data to be displayed on the UI. In this scenario, the data is pre-fetched from the backend and sent to the UI before the UI is sent to the user. Let us say we add new data content to the database; the previous data does not need to be fetched again since it has already been pre-fetched. Instead, it pre-fetches the new data and adds it to the UI before sending it to the user. That is because the previous data is statically stored in the UI hence the name static-site generation, and makes it the fastest way to fetch data and send it to the user. Static-site generation in Next js works with the getStaticProps and getStaticPaths to render static pages.

When to use each feature?

When is Client-side rendering needed?

  • When Search engine optimization is not needed in your site example, a site dashboard.
  • When the UI is a bit complex.
  • When the site has many users.

When to use Server-side rendering?

  • It can work for more dynamic sites, such as an e-commerce site with a lot of data that changes.
  • It's the opposite of client-side rendering and useful for SEO performance sites.
  • It also suits well for sites with Simple UI.

When to use Static-site Generation?

  • It works when creating a website whose data rarely change often, like a portfolio site where the data rarely changes.
  • You can use it for a blog with dynamic data content that often changes due to static-site generation having another type of pre-rendering, incremental static generation.

Ultimately, you can try these data-fetching capabilities or features to pick the best for your site or application.

Methods of Fetching Data in Next.js

In Next.js, some data fetching methods are used to fetch data. These methods are;

  • useEffect and useState hook for client-side data fetching.
  • getServerSideProps for server-side data fetching
  • getStaticProps for static-site generation
  • getStaticPath for the static-site generation, which uses dynamic routes.

So let's learn how to use them. I use an external API called Fake Store API to get data. The external API will act as a backend or database for us.

Using client-side data fetching method

Client-side data fetching is relatively easy. So let us look at how to get data on the client side.

  • In the pages folder of your Next.js app, create a file and call it index.js.

  • In the index.js file, write the following code below. First, you import useState and useEffect.

      import React from 'react'
      import { useEffect, useState } from 'react'
    
  • Next, create a function and fetch the data using the API URL. In our case, we use Fake Store API, set the data as JSON, and store it to the state. We will also get the data using the useEffect hook.

    export default function csr() {
        const [state, setState] = useState([]);
      async function getData() {
        const res = await fetch('https://fakestoreapi.com/products?limit=8');
        const data = await res.json();
        setState(data);
      }
      console.log('i am:',state);
      useEffect(() => {
        getData();
      }, [])
  • Finally, return the data to be displayed to the user by mapping the data stored in the state.
      return (
          <div>
            <h1> Welcome to My blog gallery ssg</h1>
            <div>
            {
              state.map((e) => (
                  <a key={e.id}>
                  <h2> {e.title} &rarr;</h2>
                  <img src={e.image} width={250} height={200}/>
                  <p>{e.description}</p>
                  <h3>${e.price}</h3>
              </a>
              ))
              }
            </div>
          </div>
        )
      }
    

And then run the app.

Using server-side data fetching method

Now let us work on server-side data fetching. First, let's start with the getServerSideProps;

  • To start, create a folder in the pages folder in your Next js app.
  • Create a file called index.js, then write the code below in it;
    import React from 'react'
    export const getServerSideProps = async () => {
        const res = await fetch('https://fakestoreapi.com/products?limit=8');
        const data = await res.json();
        console.log(data);
        return{
          props: {product: data}
        }
    }
    const index = ({product}) => {
      return (
        <div>
          <h1> Welcome to My blog gallery ssg</h1>
            {product.map(item =>(
            <div key={item.id}>
                <a> <h3>{item.title}</h3> </a>
                <img src={item.url} />
            </div>
        ))}
        </div>
      )
    }
    export default index

In the code above, we use a function called getServerSideProps to fetch the data. I added console.log in the function to output the JSON data from the API. By doing that, you get to be sure the data is fetched from the API. You can remove the console.log; I only used it for testing reasons.

When fetching the data from the URL, we set a limit by using ?limit=8. It limits the data gotten to eight. You can set it to any number as long as it is not more than the total data or item number.

The most important thing to note is that the getServerSideProps() function is not written in the component function, which is called index. Instead, the data is passed as a property to the component function through the return object.

    return {
      props:{product: data}
    }

In the props, the data is passed to a product object which, in turn, passes to the component. You can also write the data as a property and pass it to the component.

    return {
      props:{data}
    }

Also, another thing to note is that only the component function passes as default, not the getServerSideProps function. This also goes for the other data fetching function in Next js.

In the component function, after passing the property from the getServerSideProps, we map the data using the map function to get each item.

(Don’t mind the styling in the div or h1, you can use your styling.)

Session Replay for Developers

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — an open-source session replay suite for developers. It can be self-hosted in minutes, giving you complete control over your customer data

OpenReplay Happy debugging! Try using OpenReplay today.

Using static-site generation data fetching method

In this section, you will learn how to use the getStaticProps and getStaticPaths for a static-site generation. Now, let’s look at how getStaticProps() work. Honestly, it is easy and similar to using the getServerSideProps(), just change the function name.

    import React from 'react'

    export const getStaticProps = async () =>{
        const res = await fetch('https://fakestoreapi.com/products?limit=8');
        const data = await res.json()

        console.log(data)
        return {
            props: {blog: data}
        }
    }
    const index = ({ blog}) => {
      return (
        <div className={styles.div}>
          <h1 className={styles.header}> Welcome to My blog gallarey ssg</h1>
          <div className={styles.content}>
            {blog.map(item =>(
              <div className={styles.card} key={item.id}>
                <img src={item.image} width={200} height={200} />
                <div className={styles.text}>
                  <a> <h3>{item.title}</h3> </a>
                  <p> {item.description}</p>
                  <h3> ${item.price} </h3>
                </div>
              </div>
            ))}
          </div> 
        </div>
      )
    }
    export default index

The difference is that when the page is loaded, it generates a preloaded static page even if the item is changed from a database or, in our case, the API URL by changing the number limit to ?limit=7. That is, the page on the screen that is preloaded statically changes immediately, unlike the getServerSideProps in which the page has to be refreshed from the browser to show the updated data. This is one difference between server-side rendering and static-site generation. With that known, let us look at static path generation.

Let us say you fetch and show a list of items on a page, and you want a possibility where a user clicks on any item, and a new page generates which displays the information of the actual item that was clicked, based on the item id. In this case, you would use getStaticPaths.

Using getStaticPaths is a little confusing for some people, so I will break it down step by step.

  • First, in the pages folder in your Next js app, create a folder called products. We will use this as an example name. For now, you can use any name you want in our project.
  • In the products folder, create a file named index.js and create another called [id].js. This file will be used as a dynamic route for each item id. You can even name it [itemid].js, but for simplicity, stick with the first, as in the image below.

1

  • In the index.js file, we will write the following code to fetch and render all the item/product lists on the page. We do this using getStaticProps.
      import React from "react";
      import Link from "Next/link";
      export const getStaticProps = async () => {
        const res = await fetch("http://localhost:3000/api/data");
        const data = await res.json();
        return {
          props: { products: data },
          revalidate: 20,
        };
      };
      const index = ({ products }) => {
        return (
          <div>
            {products.map((product) => (
              <Link href={`products/${product.id}`}>
                <div key={product.id}>
                  <h1>{product.title}</h1>
                  <p>{[product.description]}</p>
                </div>
              </Link>
            ))}
          </div>
        );
      };
      export default index;
    
  • Now, to generate the static pages to show the information of each item based on id, In the [id].js file, we will fetch the data using getStaticProps()

      export const getStaticProps = async ({params}) => {
          const res = await fetch(`https://fakestoreapi.com/products/${params.id}`);
          const data = await res.json();
          console.log(params)
          console.log(data)
          return{
              props: {item: data}
          }
      }
    

    The objective for using getStaticProps() here is that Next js needs to get the id of each item in other to create a path to show the content of each item based on its id on a page. The params parameter is used as a context in the code.

  • After that, you can add the component function, which will render all the data using the map function.

      const product = ({item}) => {
        return (
          <>
              <Head>
                  <title>
                      Products page
                  </title>
              </Head>
              <h1>Product / Item</h1>
              <h2>{item.title}</h2>
              <img src={item.image} width={200} height={200}/>
              <p>{item.description}</p>
              <p>price: {item.price}</p>
          </>
        )
      }
      export default product
    
  • Above the component function, we will add the getStaticPaths function to work on the paths.

      export const getStaticPaths = async () =>{
          const res = await fetch('https://fakestoreapi.com/products');
          const prod = await res.json();
          return{
              paths: prod.map(post => (
                  {
                      params:{id: post.id.toString()}
                  }
              )),
              fallback: true,
          }
      }
    

The data is fetched in the code above, and the response is sent as JSON. In the return object, we use paths, not props, then map through it to get the id as params. Then we set the fallback to true. Not setting the fallback can lead to an error. So you have to set it. Also, we fetched the id dynamically instead of hard coding. you can check the Next js doc on how it is hard coded

Always pass the params as strings using toString().

The entire [id].js file source code will look like the one below.

    import Head from 'next/head';
    import React from 'react'

    export const getStaticProps = async ({params}) => {
        const res = await fetch(`https://fakestoreapi.com/products/${params.id}`);
        const data = await res.json();
        console.log(params)
        console.log(data)
        return{
            props: {item: data}
        }
    }
    export const getStaticPaths = async () =>{
        const res = await fetch('https://fakestoreapi.com/products');
        const prod = await res.json();
        return{
            paths: prod.map(post => (
                {
                    params:{id: post.id.toString()}
                }
            )),
            fallback: true,
        }
    }
    const product = ({item}) => {
      return (
        <>
            <Head>
                <title>
                    Products page
                </title>
            </Head>
            <h1>Product / Item</h1>
            <h2>{item.title}</h2>
            <img src={item.image} width={200} height={200}/>
            <p>{item.description}</p>
            <p>price: {item.price}</p>
        </>
      )
    }
    export default product

When you run your app, you can change the id from the URL or by clicking the list as in the screencast below.

2

Conclusion

Fetching data in Next js is easy though it can get complex, but follow and understand the basics, and you are good to go. Hopefully, this article will help when you want to build your e-commerce store or portfolio site when you have your data stored in a database Or from an API.

newsletter