react

Data fetching in Next.js 9.3+

WK

William Kurniawan

Jul 24, 2020

There are two forms of pre-rendering: Static Generation and Server-side Rendering. In this article, we will talk about three unique Next.js functions you can use to fetch data for pre-rendering:
  • getServerSideProps: Fetch data on each request (server-side rendering).
  • getStaticPaths: Specify dynamic routes to pre-render based on data.
  • getStaticProps: Fetch data at build time.

Prerequisites

I will assume that you have a basic understanding of how Next.js works, but you should be able to follow even if you are coming from a different React framework, such as create-react-app.

getServerSideProps (server-side rendering)

If you export an async function called getServerSideProps from a page, Next.js will pre-render this page on each request using the data returned by getServerSideProps.
const Page: NextPage<PageProps> = ({ data }) => {
  // render data...
};

// this function gets called on each request to this page on server-side
export const getServerSideProps: GetServerSideProps = async (context) => {
  const res = await fetch("https://www.example.com/posts");
  const data = await res.json();

  return {
    props: {
      data, // will be passed to the page component as props
    },
  };
};
When should I use getServerSideProps?
You should use getServerSideProps only if you want to pre-render a page whose data must be fetched at request time. Time to first byte (TTFB) will be slower than getStaticProps because the server must compute the result on every request, and a CDN cannot cache the result without extra configuration.
If you do not need to pre-render the data, you should consider fetching data on the client-side. This approach works well for user dashboard pages because a dashboard is a private, user-specific page, SEO is not relevant, and the page does not need to be pre-rendered.
Limitations
getServerSideProps only runs on server-side and never runs on the browser and can only be exported from a page. When you request a page directly, getServerSideProps runs at the request time, and this page will be pre-rendered with the returned props. In addition, when you request this page using client-side transitions through next/link or next/router, Next.js will send an API request to the server. This will run getServerSideProps. And then, it will return a JSON that contains the data which will be used to render the page.

getStaticProps (static generation)

If you export an async function called getStaticProps from a page, Next.js will pre-render this page at build time using the props returned by getStaticProps. Pages that use getStaticProps will generate HTML and JSON files, both of which can be cached by a CDN for performance. This makes getStaticProps much faster than getServerSideProps. Also, the code inside getStaticProps won't even be included in the JS bundle for the browser. That means you can write code such as direct database queries without them being sent to browsers.
const Page: NextPage<PageProps> = ({ data }) => {
  // render data...
};

// this function gets called at build time on server-side
export const getStaticProps: GetStaticProps = async () => {
  const res = await fetch("https://www.example.com/posts");
  const data = await res.json();

  return {
    props: {
      data, // will be passed to the page component as props
    },
  };
};
When should I use getStaticProps?
You should use getStaticProps if:
  • The data required to render the page is available at build time ahead of a user's request.
  • The data can be publicly cached (not user-specific).
  • The page must be pre-rendered for SEO purpose.
Limitations
Because getStaticProps only runs at build time, it does not receive data that's only available during request time, such as query parameters or HTTP headers as it generates a static HTML file. In development, however, getStaticProps will run on each request on server-side. Same with getServerSideProps, getStaticProps can only be exported from a page.

getStaticPaths (static generation)

I can say getStaticPaths is a "helper function" of getStaticProps. For example, if a page has dynamic routes and uses getStaticProps, it needs to define a list of paths that have to be rendered to HTML at build time. If you export an async function called getStaticPaths from a page that uses dynamic routes, Next.js will statically pre-render all the paths specified by getStaticPaths.
export const getStaticPaths: GetStaticPaths = async () => {
  const res = await fetch("https://www.example.com/posts");
  const data = await res.json();

  return {
    fallback: true,
    paths: data.map((post) => `/p/${post.slug}`),
  };
};
getStaticPaths should return an object which has fallback and paths as its key. The path key determines which paths will be pre-rendered. For example, you have a page that uses dynamic routes /pages/p/[slug].tsx. If you export the above getStaticPaths, Next.js will statically generate /p/hello-world, /p/new-world, etc. using the page component in /pages/p/[slug].tsx. The fallback key must contain a boolean value. If fallback is false, any paths not returned by getStaticPaths will render a 404 page. On the other hand, if fallback is true, any paths not returned by getStaticPaths will be served on a "fallback" version of the page. In the background, Next.js will statically generate the HTML and JSON from the requested path. This includes running getStaticProps. When that's done, the browser receives the JSON for the generated path. This will be used to automatically render the page with the required props. From the user's perspective, the page will be swapped from the "fallback" page to the actual page. At the same time, Next.js adds this path to the list of pre-rendered pages. Subsequent requests to the same path will get the previously generated page, just like other pages pre-rendered at build time.
When should I use getStaticPaths?
You should use getStaticPaths if you are statically pre-rendering pages that use dynamic routes.
Limitations
When you use getStaticProps on a page with dynamic route parameters, you must use getStaticPaths. You cannot use getStaticPaths with getServerSideProps. Same with getStaticProps, getStaticPaths only runs at build time on server-side. In development, however, getStaticPaths will run on each request on server-side. Also, getStaticPaths can only be exported from a page. You can't export it from non-page files.

Conclusion

Hopefully, this article has helped you to understand different techniques on data fetching and pre-rendering in Next.js. To learn more about these techniques, you can visit Next.js official documentation about data fetching.

Copyright © 2020 William Kurniawan. All rights reserved.