DEV Community

Cover image for Data Fetching in Next.js v12.1 Simplified (with use cases)
David Asaolu
David Asaolu

Posted on • Updated on • Originally published at beginnerfriendly.hashnode.dev

Data Fetching in Next.js v12.1 Simplified (with use cases)

Data fetching is one of the daunting topics for beginners in Next.js.
Unlike React.js where there is just one way of fetching data, Next.js provides different ways data can be fetched from an external source, which is why beginners find it difficult to understand. πŸ˜•

But, don't worry! πŸŒΈπŸ˜€

At the end of this article, you will be able to use each of the Data Fetching methods effectively in your Next.js web applications.πŸ’ͺ

Data Fetching is the process of getting stored data from an API, headless CMS and database for use in your web application.

Data Fetching Methods in Next.js

In Next.js we have 2 data rendering methods, which are:

Other features include:

Static-site Generation (SSG)

This generates static HTML pages at build time. SSG is used in webpages where the data doesn't change regularly; such as the service page of a website, FAQ page, About Us page, the home page of your web application.

In SSG, getStaticProps is used to pre-render a page at build time.

Code Sample:

Let's take a look at this route (code) below:

import Link from "next/link"

//getStaticProps 
export const getStaticProps = async () => {
  const API_URL = "https://jsonplaceholder.typicode.com/posts"
  const request = await fetch(API_URL)
  const posts = await request.json()
  return  { props : { posts } }
}

//route 
export default function Home({ posts }) {
  return (
    <div>
      <main>
        {posts.map(post => (
          <Link href={`posts/${post.id}`}>
             <a key={post.id}>
                <h3>{post.title}</h3>
             </a>
          </Link>
        ))}    
      </main>
    </div> 
  )
}

Enter fullscreen mode Exit fullscreen mode

From the code snippet above, the server-side function getStaticProps fetches data from the API URL and returns an object.

The object has a compulsory property called props. It contains the array of elements from the API.

The posts array is then destructured from the props object and passed to the Home route.

If you delete or add new posts to the API when the application is in production, the changes won't reflect in the web application unless it is rebuild after the changes have been made.

Dynamic Routing

It is used in Static-site generation to pre-render multiple pages. These pages are created at build time in production and every request in development mode.

In Dynamic Routing, getStaticPaths must be used with getStaticProps. You cannot use getStaticPaths with getServerSideProps.

Code Example:

Let's create the route for each article gotten from the API.

//gets each article according its id.
export const getStaticProps = async ({params}) => {
    const request = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`)
    const data = await request.json()
    return  {
      props : {post : data}
  }
  }

//creates a dynamic paths for all the posts
export async function getStaticPaths() {
    const request = await fetch(`https://jsonplaceholder.typicode.com/posts`)
    const data = await request.json()
    const paths = data.map((post) => ({
    params: { id: String(post.id) }
  }))

  return { paths, fallback: false }
}


export default function Post({post}) {
    return(
        <div>
            <h1>{post.id}</h1>
            <h3 className="text-xl">{post.title}</h3>
            <p>{post.body}</p>
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

getStaticPaths returns an object containing the property paths and fallback.
paths is an array of object containing the id of each posts. It tells the application how many paths is needed to be created.

fallback is set to false.

It can be set to true/false/blocking. Learn more about fallback

Incremental Static Regeneration

This allows us to use static generation without needing to rebuild the entire site. Request for changes on the static site is made at intervals already set by the developer. It allows us to update static pages after the web application has been built.

With ISR, you can retain the benefits of static while scaling to millions of pages.

Code Example:

import Link from "next/link"

//getStaticProps 
export const getStaticProps = async () => {
const API_URL = "https://jsonplaceholder.typicode.com/posts"
  const request = await fetch(API_URL)
  const posts = await request.json()
  return  { props : { posts }, 
             revalidate : 60  //In seconds
      }
}

//route 
export default function Home({ posts }) {
  return (
    <div>
      <main>
           {posts.map(post => (
            <Link href={`posts/${post.id}`}>
                <a key={post.id}>
                  <h3>{post.title}</h3>
                </a>
          </Link>
          ))}
      </main>
    </div> 
  )
}

Enter fullscreen mode Exit fullscreen mode

The code snippet above is similar to SSG. The difference is that getStaticProps returns a revalidate property which tells Next.js to re-generate the page at most once every 60 seconds.

If any changes is made to the posts (API) when the application is in production, the changes are reflected in the next 60secs.

Server-side Rendering

This builds HTML pages at runtime or request time. Server-side rendering is used in web applications where the page's data changes on every request.

In SSR, getServerSideProps is used to pre-render a page whose data must be fetched at request time.

Code Example:


export async function getServerSideProps() {
   const request = await fetch(<API_URL/>)
  const comments = await request.json()
  return  {
    props : {comments}
}
}


const CommentsPage = () => {// jsx }
export default CommentsPage
Enter fullscreen mode Exit fullscreen mode

From the code snippet above, getServerSideProps fetches comments made on each article at runtime during every request.
If new comments are added, it appears immediately the web application is refreshed.

Client-side Rendering

It is similar to a single-page React app; where the data is not pre-rendered, but the data changes per each request. It is also used on pages where SEO (Search Engine Optimization) is not needed.
In CSR, data fetching is done when the component or page mounts or when some specific actions, like a button click, are executed on the page.

React's useState() and useEffect() is used. Another alternative is SWR hook created by the Next.js team

Code Example:

//Using React's useState and useEffect hooks
import { useState, useEffect } from "react";

export default function Posts() {
    const [posts, setPosts] = useState([])

    async function fetchPosts() {
        const request = await fetch("https://jsonplaceholder.typicode.com/posts")
        const data = await request.json()
        setPosts(data)
    }

useEffect(()=>{
    fetchPosts()
}, [])

    return (
        <div>
            {posts.map(post => <p key={post.id}>{post.title}</p>)}
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Depending on your application's use case, Next.js provides suitable methods for fetching and utilizing data.
When requesting data from an external source, you just have to figure out how often data changes in the application, then pick the best rendering method for each call to the external resource.

Thank you for reading!

arshadayvid image

Further Reading

  1. Next.js Complete Tutorial for Beginners (YouTube)

  2. Understanding Next.js Data Fetching (CSR, SSR, SSG, ISR)

  3. Data fetching strategies in NextJS

  4. Next.js Data Fetching Documentation

Writer's Corner

Hi, I am open to freelance technical writing gigs and remote opportunities. Let's work together. πŸ“§: asaoludavid234@gmail.com

Feel free to connect with me on Twitter and LinkedIn

Discussion (0)