DEV Community

Hamza Khan
Hamza Khan

Posted on

πŸš€ 5 Effective Ways to Make API Requests in Next.js 🌐

Making API requests is a crucial part of building modern web applications, and Next.js provides several efficient ways to handle these requests. Whether you're fetching data from a third-party API, interacting with your own backend, or consuming GraphQL, Next.js has a variety of built-in tools and patterns that make it easy to work with APIs.

In this post, I’ll walk you through 5 effective ways to make API requests in Next.js, with code examples for each approach. Let’s dive in! ⚑

1. πŸ”„ Using getStaticProps for Static Site Generation (SSG)

getStaticProps is one of the most powerful methods in Next.js for Static Site Generation (SSG). It allows you to make API requests at build time, which is perfect for pages that don’t need to be updated frequently, like blogs or documentation sites.

Example:

// pages/index.js
export async function getStaticProps() {
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();

  return {
    props: {
      data,
    },
    revalidate: 60, // Revalidate every 60 seconds
  };
}

export default function Home({ data }) {
  return (
    <div>
      <h1>Static Data</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Why use it?

This method makes your site blazing fast since data is fetched at build time and pages are served as static HTML. It's perfect for SEO and performance optimization.


2. βš™οΈ Using getServerSideProps for Server-Side Rendering (SSR)

When you need to fetch data on every request, you can use getServerSideProps. This is ideal for content that needs to be updated frequently or for user-specific data.

Example:

// pages/user.js
export async function getServerSideProps() {
  const res = await fetch('https://api.example.com/user');
  const data = await res.json();

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

export default function User({ data }) {
  return (
    <div>
      <h1>User Data</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Why use it?

getServerSideProps is perfect for fetching data that needs to be dynamic and served fresh on every request, like user profiles or personalized content.


3. πŸ”§ Using API Routes for Backend Logic

Next.js comes with built-in API routes, which allow you to define your own server-side endpoints. You can use API routes to fetch data from external APIs or databases, handle authentication, or even process payments.

Example:

// pages/api/data.js
export default async function handler(req, res) {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  res.status(200).json(data);
}
Enter fullscreen mode Exit fullscreen mode

Then, you can fetch data in your pages from this API route:

// pages/index.js
export async function getStaticProps() {
  const res = await fetch('http://localhost:3000/api/data');
  const data = await res.json();

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

export default function Home({ data }) {
  return (
    <div>
      <h1>Data from API Route</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Why use it?

API routes are great for handling custom logic on the server side, such as processing data before returning it to the client or connecting to secure databases.


4. 🌍 Client-Side Fetching with useEffect

Sometimes, you want to fetch data on the client side, especially when you need to fetch data after the page loads or when responding to user actions (e.g., clicking a button). For this, you can use useEffect and the fetch API.

Example:

import { useState, useEffect } from 'react';

export default function ClientFetch() {
  const [data, setData] = useState(null);

  useEffect(() => {
    async function fetchData() {
      const res = await fetch('https://api.example.com/data');
      const result = await res.json();
      setData(result);
    }
    fetchData();
  }, []);

  return (
    <div>
      <h1>Client-Side Data</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Why use it?

Client-side fetching is perfect for dynamic interactions where data doesn’t need to be available at build or request time, such as loading user comments or updating a dashboard in real-time.


5. πŸ“Š Fetching GraphQL Data with graphql-request

For applications using GraphQL, the graphql-request library is a simple and efficient way to make API requests. You can use it in getStaticProps, getServerSideProps, or client-side.

Example:

npm install graphql-request
Enter fullscreen mode Exit fullscreen mode
import { GraphQLClient } from 'graphql-request';

const client = new GraphQLClient('https://api.example.com/graphql');

export async function getStaticProps() {
  const query = `
    query {
      allPosts {
        title
        content
      }
    }
  `;
  const data = await client.request(query);

  return {
    props: {
      posts: data.allPosts,
    },
  };
}

export default function Posts({ posts }) {
  return (
    <div>
      <h1>GraphQL Data</h1>
      {posts.map((post) => (
        <div key={post.title}>
          <h2>{post.title}</h2>
          <p>{post.content}</p>
        </div>
      ))}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Why use it?

GraphQL makes it easy to query only the data you need, and graphql-request simplifies the syntax for making those requests in Next.js.


🎯 Conclusion

Next.js offers multiple ways to handle API requests, depending on your use case:

  • SSG with getStaticProps for fast, pre-rendered content.
  • SSR with getServerSideProps for dynamic content on every request.
  • API routes for handling server-side logic.
  • Client-side fetching with useEffect for dynamic data updates.
  • GraphQL requests with graphql-request for working with structured APIs.

By leveraging these different methods, you can build highly performant and scalable applications while keeping data fetching optimized. What’s your preferred way to handle API requests in Next.js? Let me know in the comments below!πŸ‘‡


Further Reading:


Happy coding! πŸ’»βœ¨

Top comments (0)