DEV Community

Mina
Mina

Posted on • Updated on

A Simple Guide to fetch data using getStaticProps and getServerSideProps in Next.js

In Next js, data fetching is a strategy. Next.js uses getStaticProps or getServerSideProps to enhance different fetching capabilities. Even though both are used to pre-render data, the former uses static generation whilst the latter uses server side rendering.

Hmm... ok but do I need page pre-rendering?

  1. Does the data you want to display change frequently? Does your data need to be updated frequently like a stock/crypto exchange dashboard or an online store showing its real time available stocks.

  2. Does your page carry private data like user's personal information? It is not important for your data to appear on search engine results?

  3. Do you prefer your page to be immediately available even with some partially available data rather than waiting for the data to be fully ready?

If you are ticking any of the questions above, it might be better just to stick to client-side fetching for better performance.

If you have decided to use GetStaticProps or GetServerSideProps, how would you use them differently?

Next.js doesn’t allow both Static Generation and SSR to be configured on the same page but you can opt to use either on each page to have different data fetching solutions for your application.

GetStaticProps and GetServerSideProps are async functions that need to be named exactly as they are and return an object that is passed as props and exported on a page like so.

export async function getStaticProps() {
    const data = await fetch('https://.../products')
    const products = await data.json()
    return { props: { products } }
}
Enter fullscreen mode Exit fullscreen mode
export async function getServerSideProps() {
  const data = await fetch('https://.../products')
  const products = await data.json()
  return { props: { products } }
}
Enter fullscreen mode Exit fullscreen mode

The code within the function only gets executed on the server and pre-renders the page. However, GetStaticProps pre-renders the data at build time, whereas getServerSideProps runs at request time.

GetStaticProps is best suited for data that doesn’t change frequently such as blog posts or news articles because unlike GetServerSideProps, when data is fetched, it generates a static HTML and stored in a JSON file so it can be cached and immediately available before loading. However, for less static and more dynamic pages, this can be leveraged by using an Incremental Static Generation feature. By simply adding another key value pair, a key named “revalidate” with its value set to any time in seconds in the returned statement, it tells the page to regenerate at every given second and updates the data even after the build time without deploying it again.

export async function getStaticProps() {
  const data = await fetch('https://.../products')
  const products = await data.json()
  return { 
     props: { products },
     revalidate: 10 
  }
}
Enter fullscreen mode Exit fullscreen mode

Unlike getStaticProps, getServerSideProps doesn’t cache any data. It fetches new data on every request which often results in a slower performance but it has access to incoming requests or user’s specific data.

params is a parameter object that can be destructured from the context prop. It gives you access to the route, but in the getStaticProps function it only works for a default route. In order for it to work for a dynamic route, the getStaticPaths function has to come into play. It must return an object which includes two keys, a ‘paths’ key with an array that gives pre-generated route instances to be pre-rendered ahead of time and a ‘fallback’ key that can be set to false if all possible route instances are provided. The other option is to set the fallback to true if not all possible page routes are provided, which means it can have a fallback to render rarely visited pages. In case of the latter, a fallback state is needed (as in the condition below) so it can show a loading indicator before the data is fetched. Alternatively, you can set the fallback to a value in a string “blocking”, in this case your app will wait until the page gets fully generated before rendering data without any loading signs.

export async function getStaticPaths() {
  return { 
    paths: [
            {params: {product: item1 }},
            {params: {product: item2 }},
            {params: {product: item3 }},
           ],
          fallback: false
        }
}

export async function getStaticProps(context) {
   const { params } = context

   const data = 
     await fetch(`https://.../products/${params.product}`)
   const product = await data.json()

   return { 
     props: { product },
     revalidate: 10 
   }
}

function Product (props) {
  const { product } = props
  if (!product) {
    return <p>loading</p>
  }
  return <div>
           <p>{product.name}</p>
           <p>{product.description}</p>
           ...
         </div>

}
Enter fullscreen mode Exit fullscreen mode

params is also supported in getServerSideProps and in fact, it is much simpler as it can extract both default and dynamic routes. In addition to that, the context props in getServerSideProps can give access to the req and res object that you can write server side code with.

export async function getServerSideProps(context) {
   const { params, req, res } = context

   const data = 
     await fetch(`https://.../products/${params.product}`)
   const product = await data.json()

   return { 
     props: { product },
   }
}
Enter fullscreen mode Exit fullscreen mode

Next.js offers powerful pre-rendering data fetching options to optimize your app but as always, it is not the solution for all. Now you might be very tempted to use them but sometimes, it is just as good using the client side fetching to give better user experience - so planning what works best for you is key because it will save your time! Oh boy, how many times have I tried these fetching methods, only to realize that I am better off with the old traditional client side fetching.

Top comments (10)

Collapse
 
jm066 profile image
Mina

Thank you!

Collapse
 
ivanms1 profile image
Ivan

Great article!

Collapse
 
jm066 profile image
Mina

Thanks Ivan!

Collapse
 
srakesh563 profile image
Rakesh Sharma

Is it work for internal api?
Like I have data file in my pages/api/data.[js,json]
As seen you use third party api for data fetching, is this code works without third party api fetching?
Hope you get my point.
I just started learning these languages

Collapse
 
quintron profile image
Quintin Maseyk

Thank you!

Collapse
 
wajidjmi profile image
wajidjmi

Awesome explanation.

Collapse
 
jm066 profile image
Mina

Thank you! :)

Collapse
 
developerbishwas profile image
Bishwas Bhandari

Thanks for sharing

Collapse
 
jamesl0724 profile image
Lin • Edited

Was very helpful for me and extraordinary explanation. Thank you, Mina.
But revalidate works on production mode?