DEV Community

Cover image for Next.js Data Fetching: Optimize Performance with the Right Method
Ryan Aulia
Ryan Aulia

Posted on • Updated on • Originally published at aulianza.id

Next.js Data Fetching: Optimize Performance with the Right Method

Next.js, a popular React framework, provides powerful features for building server-rendered and statically generated web applications. One crucial aspect of web development is fetching data from APIs or databases. In this article, we will explore the different data fetching methods available in Next.js and understand when and how to use them. Whether you're a beginner or have some experience with Next.js, this guide will help you grasp the basics of data fetching in a simple and understandable manner.

Static Data Fetching

Static data fetching is ideal for content that remains unchanged across all requests. It involves fetching data at build time, enabling Next.js to pre-render the pages with the data. This approach ensures fast loading times and reduces the load on your server during runtime. To implement static data fetching, you can use Next.js' getStaticProps function.

Example:

// pages/index.tsx
import React from 'react';
import { GetStaticProps } from 'next';

interface HomeProps {
  data: string;
}

export const getStaticProps: GetStaticProps<HomeProps> = async () => {
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();

  return {
    props: {
      data,
    },
  };
};

const HomePage: React.FC<HomeProps> = ({ data }) => {
  return (
    <div>
      <h1>Welcome to my website!</h1>
      <p>{data}</p>
    </div>
  );
};

export default HomePage;
Enter fullscreen mode Exit fullscreen mode

In this example, the getStaticProps function fetches data from the specified API endpoint (https://api.example.com/data). The fetched data is then passed as a prop (data) to the HomePage component, which is pre-rendered at build time with the data.

Server-side Rendering (SSR)

Server-side rendering allows you to fetch data on each request made to the server. This method is useful when you need to display dynamic content that can change frequently. When a user visits a page, the server fetches the data and generates the HTML, which is then sent to the client. Next.js provides the getServerSideProps function to implement server-side rendering.'

Example:

// pages/post/[id].tsx
import React from 'react';
import { GetServerSideProps } from 'next';

interface PostProps {
  data: {
    title: string;
    body: string;
  };
}

export const getServerSideProps: GetServerSideProps<PostProps> = async (context) => {
  const { params } = context;
  const res = await fetch(`https://api.example.com/posts/${params?.id}`);
  const data = await res.json();

  return {
    props: {
      data,
    },
  };
};

const PostPage: React.FC<PostProps> = ({ data }) => {
  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.body}</p>
    </div>
  );
};

export default PostPage;
Enter fullscreen mode Exit fullscreen mode

In this example, the getServerSideProps function fetches the data for a specific post based on the id parameter from the API endpoint (https://api.example.com/posts/[id]). The fetched data is then passed as a prop (data) to the PostPage component, which is rendered on the server-side for each request.

Client-side Rendering (CSR)

Client-side rendering is suitable for scenarios where data needs to be fetched after the initial page load. This method is commonly used for interactive components or when the data is not required for SEO purposes. With client-side rendering, the page is initially rendered without the data, and the data is fetched asynchronously on the client-side using JavaScript. Next.js supports client-side rendering through the useEffect hook or other libraries like React Query or SWR.

Example:

// pages/products.tsx
import React, { useEffect, useState } from 'react';

const ProductsPage: React.FC = () => {
  const [products, setProducts] = useState<string[]>([]);

  useEffect(() => {
    const fetchProducts = async () => {
      const res = await fetch('https://api.example.com/products');
      const data = await res.json();
      setProducts(data);
    };

    fetchProducts();
  }, []);

  return (
    <div>
      <h1>Products</h1>
      <ul>
        {products.map((product) => (
          <li key={product}>{product}</li>
        ))}
      </ul>
    </div>
  );
};

export default ProductsPage;
Enter fullscreen mode Exit fullscreen mode

In this example, the useEffect hook is used to fetch the products data from the API endpoint (https://api.example.com/products). The fetched data is stored in the products state variable, which triggers a re-render of the component. The product names are then displayed in a list on the client-side.

Incremental Static Regeneration (ISR)

Incremental Static Regeneration combines the benefits of static and server-side rendering. It allows you to pre-render static pages at build time and then regenerate them periodically or on-demand. This approach is ideal for content that changes occasionally but doesn't require real-time updates. Next.js offers the revalidate option in getStaticProps to enable ISR.

Example:

// pages/blog/[slug].tsx
import React from 'react';
import { GetStaticProps, GetStaticPaths } from 'next';

interface BlogProps {
  data: {
    title: string;
    content: string;
  };
}

export const getStaticProps: GetStaticProps<BlogProps> = async (context) => {
  const { params } = context;
  const res = await fetch(`https://api.example.com/blog/${params?.slug}`);
  const data = await res.json();

  return {
    props: {
      data,
    },
    revalidate: 60, // Re-generate page every 60 seconds
  };
};

export const getStaticPaths: GetStaticPaths = async () => {
  const res = await fetch('https://api.example.com/blog');
  const data = await res.json();

  const paths = data.map((post: { slug: string }) => ({
    params: { slug: post.slug },
  }));

  return {
    paths,
    fallback: true,
  };
};

const BlogPage: React.FC<BlogProps> = ({ data }) => {
  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.content}</p>
    </div>
  );
};

export default BlogPage;
Enter fullscreen mode Exit fullscreen mode

In this example, the getStaticProps function fetches the blog post data based on the slug parameter from the API endpoint (https://api.example.com/blog/[slug]). The fetched data is then passed as a prop (data) to the BlogPage component. Additionally, the getStaticPaths function is used to generate dynamic paths for all blog posts. The page will be re-generated every 60 seconds to ensure the content is up to date.

Conclusion:
Understanding the different data fetching methods in Next.js is essential for building efficient and performant web applications. By utilizing static data fetching, server-side rendering, client-side rendering, and incremental static regeneration, you can create responsive and optimized web experiences. Experiment with these approaches and choose the one that best suits your project's needs. Happy coding!

Top comments (1)

Collapse
 
aulianza profile image
Ryan Aulia

Hi, kindly leave a like and comment if you got something to ask! 🔥