Understanding Next.js Data Fetching (CSR, SSR, SSG, ISR)
Tags: nextjs, react, tutorial, typescript
Published: 2021-09-02 13:53:51

When I started to learn Next.js, I got overwhelmed with the list of abbreviations that looks similar, I didn't know what it is and what is the difference. It is quite confusing because when using Create React App, we usually only use 1 strategy to fetch data from API which is using `useEffect`.

Next.js has many data fetching strategies. Although initially Next.js was well known to be a Server-Side Rendering Framework, it turns out that Next.js has 4 methods of Data Fetching. Here is the short explanation each so you get familiar with the abbreviation of CSR, SSR, SSG, ISR.

- CSR - Client-Side Rendering, this is the usual kind of data fetching using `useEffect`, it will fetch the data from the API every single page request on the **client-side** (after the page is rendered, then the function will run).
- SSR - Server-Side Rendering, will run a **special function** to fetch data from API every page request on the **server-side** (before the page is loaded, that special function will run first, creating a delay, then after that, it will serve the page).
- SSG - Static Site Generation, will run a **special function** to fetch data **once** when that page builds.
- ISR – Incremental Static Regeneration, this is a new thing, shortly put, a combination of SSG, and SSR, where it served statically, but at a **certain time and certain condition** that page will rebuild and fetch the data from the API again.

Don't worry if you didn't get that, because I will be explaining it thoroughly, just familiarize the words first.

---

I mentioned before that there is a special function that will run when using a specific data fetching method. Keep that in mind as I will show you what is that special function.

This code example will fetch a date-time from an API using axios, then render it on the page. It is useful to see the date-time so we can truly know when the API is hit.

## Client-Side Rendering (CSR)

Special Function: `useEffect`

[Demo Site](https://next-render.theodorusclarence.com/render/csr)

### Code Example

```tsx
export default function CSRPage() {
  const [dateTime, setDateTime] = React.useState<string>();

  React.useEffect(() => {
    axios
      .get('https://worldtimeapi.org/api/ip')
      .then((res) => {
        setDateTime(res.data.datetime);
      })
      .catch((error) => console.error(error));
  }, []);

  return (
    <main>
      <TimeSection dateTime={dateTime} />
    </main>
  );
}
```

### Demo

![CSR](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6xnmxlvw6jro0alwfgq5.gif)
 
Terms:

- PT → Preview Time, the time shown when the API is hit. Can be seen in the middle.
- RT → Real-Time, the real ticking time updating every second, can be seen on the right bottom corner

Video Description:

1. Page reloads on 15:46:03 Real-Time (RT), then a LOADING indicator is shown
2. After about 1s, Preview Time is showing 15:46:04(PT)

### Keys to Emphasize

1. **useEffect function**, this function is the key indicator that a page is using Client-Side Rendering.
2. **LOADING indicator**, because the data fetching runs after the page is rendered, the data is not fetched instantly, therefore showing a loading state.
3. **Data is fetched on every page request**, which is why the time shown is different for each reloads.

![0-csr-illustration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wlfrny1vq3hx9gcv3djz.png)
 

---

## Server Side Rendering (SSR)

Special Function: `getServerSideProps`

[Demo Site](https://next-render.theodorusclarence.com/render/ssr)

### Code Example

```tsx
export default function SSRPage({ dateTime }: SSRPageProps) {
  return (
    <main>
      <TimeSection dateTime={dateTime} />
    </main>
  );
}

export const getServerSideProps: GetServerSideProps = async () => {
  const res = await axios.get('https://worldtimeapi.org/api/ip');

  return {
    props: { dateTime: res.data.datetime },
  };
};
```

### Demo

![SSR](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36kbv9j6d5y7b2y1eqr2.gif) 

Video Description:

1. Clicked the link on 16:32:38(RT), a slight pause for 2s, then page loads showing 16:02:40(PT)

### Keys to Emphasize

1. **getServerSideProps function**, this function is the key indicator that a page is using Server-Side Rendering.
2. **DELAY before render, and no LOADING indicator**, the data is fetched before the page is rendered, so there will be a slight **delay** where the **API is being hit** at the moment, then it will show the page without loading indicator
3. **Data is fetched on every page request**, which is why the time shown is different for each reloads.

![1-ssr-illustration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b9m35yuat5eyz5h20noh.png) 

---

## CSR vs SSR

Here is the difference between CSR vs SSR, keep an eye on **delay** and **loading** indicators.

![CSRvsSSR](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/be9xqwr7lzv0x60878gv.gif)
 

Video Description:

1. When clicking CSR, with no delay a LOADING text is visible for a second, then the Preview Time loads.
2. When clicking SSR, a slight delay happened, then the page loads.

### Keys to Emphasize

1. **CSR hit the API after the page loads.**
2. **SSR hit the API before the page loads.**

![2-csr-vs-ssr](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qkye8ahmbvuocgzge8x3.png)
 

### Short addition

I will probably create a new post about the pros and cons of each method, but when using **CSR** the SEO is not really great because the data is only fetched after the page renders. This is useful and convenient when we are creating a page with a gated authentication, as you don't really need SEO for pages like the dashboard, edit profile page, etc.

But, for the SSR, although it creates a delay, data that was fetched is injected and helps SEO. This is quite useful for a thread or post that we need to get traffic into, like Reddit or some sort.

---

## Static Site Generation (SSG)

Special function: `getStaticProps`

[Demo Site](https://next-render.theodorusclarence.com/render/ssg)

### Code Example

```tsx
export default function SSGPage({ dateTime }: SSGPageProps) {
  return (
    <main>
      <TimeSection dateTime={dateTime} />
    </main>
  );
}

export const getStaticProps: GetStaticProps = async () => {
  const res = await axios.get('https://worldtimeapi.org/api/ip');

  return {
    props: { dateTime: res.data.datetime },
  };
};
```

### Demo

![SSG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gkdkdffky1lxb5yguuem.gif)
 

Video Description:

1. Preview Time is showing 13:39:36(PT). But the real-time is 16:16:59(RT), about 3 hours late.
2. Reloading and going back and forth to the home page did not change anything. 

### Keys to Emphasize

1. **getStaticProps function**, this function is the key indicator that a page is using Static Site Generation.
2. **Fetched when running** `yarn build`, the API will be hit **ONLY** when the application is building. This is why the time is at 13:39, while the real-time is 16:17.
3. **Data will not change because no further fetch**, which is why the time shown is the same for each reloads.

![3-ssg-illustration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/62x0vmtmey8khh6nhja3.png)
 

---

## Incremental Static Regeneration

Special function: `getStaticProps` + `revalidate`

[Demo Site](https://next-render.theodorusclarence.com/render/isr-20)

### Code Example

```tsx
export default function ISR20Page({ dateTime }: ISR20PageProps) {
	return (
    <main>
      <TimeSection dateTime={dateTime} />
    </main>
  );
}

export const getStaticProps: GetStaticProps = async () => {
  const res = await axios.get('https://worldtimeapi.org/api/ip');

  return {
    props: { dateTime: res.data.datetime },
    revalidate: 20,
  };
};
```

### Demo

![ISR](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/koq4o1ohev85i4xas2ue.gif)
 

Disclaimer: Revalidate time is set to 20 seconds.

Video Description:

1. At first, it was 16:40:12(PT), and real-time when reloading is 16:40:25(RT) and 16:40:29(RT). In those 2 reload, Preview Time (PT) did not change.
2. Then, when 16:40:32(RT) (20s after initial), reload is done twice, the first time on 16:40:36(RT) and 16:40:40(RT). The Preview Time change to 16:40:37(PT) after the **second reload.**

### Keys to Emphasize

Now, this is might be confusing for you, but here is the key I want you to look at.

1. **When in a 20-second cooldown span–16:40:12(RT) - 16:40:32(RT),** reloading doesn't trigger changes. This is because the page is in a **cooldown** state, as we set on the `revalidate` key.
2. **After the 20-second cooldown–16:40:32(RT),** we did 2 reloads.
    1. First Reload at 16:40:36(RT), we know that it is not on the cooldown state anymore. The first visit after the cooldown state is **off,** is going to trigger **page rebuild**. Page rebuild meaning, only this certain page is going to be rebuild. Not the whole application. The fetch API will run in the background, but there will be **no changes** on the Preview Time
    2. Second Full Reload at 16:40:40(RT), the Preview Time change to 16:40:37(PT). Exactly a second after the page rebuild (which means the rebuild takes about 1s). This second reload is going to serve that rebuilt page from the previous reload.

![4-cooldown-on-isr](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hk9z4stuebigj8hhqpsv.png)

![5-cooldown-off-isr](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k1dxm9x93cve5844h1do.png)
  

### Revisiting Page vs Full Reload

![isr-revisit-reload](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5tw6uu94jt9b449jaqnf.gif)
 

Terms:

1. Revisiting pages → navigating using next/link (going back to home, then to that page again)
2. Full reload → doing reload at a website (command+r)

Video Description:

1. Revisiting pages at the first time 18:38:45(RT), will **trigger rebuild,** but after the **second** revisit, the Preview Time **did not change**.
2. After a **full reload,** then Preview Time is changed to 18:38:45(PT)

Note:

1. **The first reload does not have to be a full reload**, we can go back to the home page, then to that page again (revisit), it will trigger the rebuild as long as we are not in the cooldown state.
2. **But, the second reload must be a full reload.** Going back to the home page, then to the page again won't change the new Preview Time.

Now, this is a case where we are assuming that only 1 person is accessing the website. But, that reloads will happen **every person** visit while still respecting the cooldown state.

### Is it going to be rebuilt every 20s then?

No.

When the cooldown is off, if no one visits the page, then that page **will not rebuild**, even after long past the 20s.

But, the **first** person that visits when the **cooldown state is off**, is going to **trigger a rebuild.** That person won't be seeing changes. But, the changes will be served for **the next full reload**.

![6-cooldown-illustration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8une4um2qtp7pr9r85xu.png)

## Conclusion

That's all, folks!

If you have understood this material, I suggest you to read more about [How to choose between them](https://theodorusclarence.com/blog/nextjs-fetch-usecase). I provide 4 metrics for you to consider and some example!


---

> Originally posted on [my personal site](https://theodorusclarence.com/?ref=devto), find more [blog posts](https://theodorusclarence.com/blog?ref=devto) and [code snippets library](https://theodorusclarence.com/library?ref=devto) I put up for easy access on my site 🚀