DEV Community

Cover image for Different ways to fetch data in Next.js (server-side) and when to use them
James Wallis
James Wallis

Posted on • Originally published at wallis.dev

Different ways to fetch data in Next.js (server-side) and when to use them

When building an application powered by Next.js it's probable that you'll need to fetch data from either a file, an internal API route or an external API such as the Dev.to API. Moreover, determining what data fetching method to use in a Next.js application can easily become confusing - especially as it isn't as simple as making an API request inside your components render function, as you might in a stock React app.

The following guide will help you carefully select the server-side data fetching method that suits your app (FYI you can use multiple methods in a single app). For each method, I have outlined when it runs, it's benefits and an example of when you could use the method in your Next.js application.

The following methods fetch data either at build time or on each request before the data is sent to the client.

getStaticProps (Static Generation)

Fetch data at build time.

The getStaticProps method can be used inside a page to fetch data at build time, e.g. when you run next build. Once the app is built, it won't refresh the data until another build has been run.

Note: Added in Next 9.3

Usage:

export async function getStaticProps(context) {
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  if (!data) {
    return {
      notFound: true,
    }
  }

  return {
    props: {}, // will be passed to the page component as props
  }
}
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • It enables the page to be statically generated and will produce fast load times of all the data fetching methods.
  • If each page in your app uses getStaticProps (or no server-side data fetching methods) then Next.js will be able to export it into static HTML using next export. This is advantageous if you want to create a static site that can be hosted on places such as GitHub Pages.
  • The data is rendered before it reaches the client - great for SEO.

Example usage:

Imagine you have a personal blog site that renders pages from markdown files at build time. getStaticProps can read the files and pass the data into the page component at build time. When you make a change to a blog entry, you rebuild the site to see the changes. ameira.me, a site I built, uses this method - each time Ameira makes a change to her portfolio, Vercel automatically rebuilds and republishes the site.

getServerSideProps (Server-side Rendering)

Fetch data on each request.

The getServerSideProps method fetches data each time a user requests the page. It will fetch the data before sending the page to the client (as opposed to loading the page and fetching the data on the client-side). If the client makes a subsequent request, the data will be fetched again.

Note: Added in Next 9.3

Usage:

export async function getServerSideProps(context) {
  const res = await fetch(`https://...`)
  const data = await res.json()

  if (!data) {
    return {
      notFound: true,
    }
  }

  return {
    props: {}, // will be passed to the page component as props
  }
}
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • The data is refreshed each time a client loads the page meaning that it is up to date as of when they visit the page.
  • The data is rendered before it reaches the client - great for SEO.

Example usage:

getServerSideProps is perfect for building an application that requires the client to see the most up to date information, but isn't refreshed while the client is on the page (see client-side for constantly updating information). For example, if I had a page on my personal site that displayed information about my last GitHub commit or my current Dev.to stats, I'd want these fetched each time a page is viewed.

getInitialProps (Server-side Rendering)

Fetch data on each request.

getInitialProps was the original way to fetch data in a Next.js app on the server-side. As of Next.js 9.3 you should use the previously discussed methods over getInitialProps but I'm including it in this article because:

  1. It can still be used - although the Next.js maintainers advise you not to as getStaticProps and getServerSideProps enable you to choose from static or server-side data fetching.
  2. Knowing about getInitialProps helps when you come across an old Stack Overflow query that mentions it, and also that you shouldn't just copy and paste that solution!.

Note: If you're on Next.js 9.3 or above, use the two methods above.

Usage:

function Page({ stars }) {
  return <div>Next stars: {stars}</div>
}

Page.getInitialProps = async (ctx) => {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const json = await res.json()
  return { stars: json.stargazers_count }
}

export default Page
Enter fullscreen mode Exit fullscreen mode

Benefits:

Same as getServerSideProps - use getServerSideProps!

Example usage:

Same as getServerSideProps - use getServerSideProps!

How to decide which one to use?

When using Next.js, I always aim to make each page static. This means that I try to avoid using getServerSideProps and favour getStaticProps. However, if the data that I am fetching changes often then of course I will use getServerSideProps. I never use getInitialProps anymore.

So normally I try getStaticProps and if that is causing data to become outdated then I move to getServerSideProps.

A word on client-side data fetching

This article hasn't covered any client-side data fetching methods but you can use the useEffect hook to make the request or the useSwr custom hook made by Vercel engineers which implements stale-while-revalidate.

SWR is a strategy to first return the data from cache (stale), then send the fetch request (revalidate), and finally come with the up-to-date data.

- swr.vercel.app

SWR Usage:

import useSWR from 'swr'

function Profile() {
  const { data, error } = useSWR('/api/user', fetcher)

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}
Enter fullscreen mode Exit fullscreen mode

Final words

In this article, I've introduced three Next.js methods that can be used to fetch data either at build time or before each client request.

Liked this article? Hit the like button!

Thanks for reading!

Discussion (9)

Collapse
konrud profile image
Konstantin Rouda • Edited on

Nice article. You could also say a word about using getStaticProps with Incremental Static Regeneration which allows you to use both statically generated content with dynamic updates when needed.

Here's what Next.JS documentation says about it:
Inspired by stale-while-revalidate, background regeneration ensures traffic is served uninterruptedly, always from static storage, and the newly built page is pushed only after it's done generating.

Example

function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// revalidation is enabled and a new request comes in
export async function getStaticProps() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  return {
    props: {
      posts,
    },
    // Next.js will attempt to re-generate the page:
    // - When a request comes in
    // - At most once every second
    revalidate: 1, // In seconds
  }
}

export default Blog
Enter fullscreen mode Exit fullscreen mode
Collapse
jameswallis profile image
James Wallis Author

Thanks for adding this! I’ve used it before and it’s pretty slick.

Collapse
cucheng profile image
Trương Đình Chiến

Hi author, i have a proplem relate about fecth data in nextjs,, can you suggest me.
I building a blog like dev.to.I have router for post like /post/[slug].tsx.

Im using getStacticProps for all post and every the post user can leave a comment like this comment.
When user add comment, if refresh the post then will see comment not show because the post had get from cache before.
At second refresh it get updated.

getServerSideProps can fix it but i think it not good for this case.All post should cache to fast load.

And can you help me or suggest some solution.
Thank so much.

Collapse
jameswallis profile image
James Wallis Author

If you want the comments to be updated each time the page loads you need to use getServerSideProps. If you are wanting fast pages use getStaticProps and re-fetch the data once the page has loaded - check out swr.vercel.app/ which is a React hook that can help with this.

Collapse
cucheng profile image
Trương Đình Chiến

Tks bro, i still using swr to fecth data from api.But i think post list should use getStaticProps togenerated at build time and will be reused on each request.

Thread Thread
jameswallis profile image
James Wallis Author

Yeah that sounds sensible.

Collapse
sereiodobrejo profile image
Sereio-do-Brejo

Easy to understand and complete. Nice work !

Collapse
willzmu profile image
Wilfred • Edited on

Great article and it's helped me understand the difference between getStaticProps and getServerSideProps. Thanks

Collapse
jameswallis profile image
James Wallis Author

Thanks, happy to have helped!