Data Fetching in Next.js
Tags: nextjs, react, webdev
Published: 2023-02-05 22:18:31

by [Favour Ogbonda](https://blog.openreplay.com/authors/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](https://fakestoreapi.com/docs) 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.`
```javascript
    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](https://fakestoreapi.com/docs), set the data as JSON, and store it to the state. We will also get the data using the `useEffect` hook.

```javascript
    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.
```javascript
    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;

```javascript
    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.
```javascript
    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.
```javascript
    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.)




<h2>Session Replay for Developers</h2> 
<p><em>
Uncover frustrations, understand bugs and fix slowdowns like never before with <strong><a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a></strong> — an open-source session replay suite for developers. It can be <strong>self-hosted</strong> in minutes, giving you complete control over your customer data
</em></p>
<img alt="OpenReplay" width="768" height="400" src="https://blog.openreplay.com/assets/overview_Z17Qdyg.png" class="astro-UXNKDZ4E" loading="lazy" decoding="async">
<em>Happy debugging! <a href="https://openreplay.com" target="_blank">Try using OpenReplay today.</a></em>





## 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. 
```javascript
    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](https://blog.openreplay.com/images/data-fetching-in-next-js/images/image01.jpeg)

- 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`.
```javascript
    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()`
```javascript
    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.
```javascript
    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.
```javascript
    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](https://nextjs.org/docs/basic-features/data-fetching/get-static-paths) 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.
```javascript
    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](https://blog.openreplay.com/images/data-fetching-in-next-js/images/image02.gif)

## 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](https://blog.openreplay.com/newsletter_Z1P0UIP.png)](https://newsletter.openreplay.com/)