How to Fetch Data in Nextjs

Introduction Fetching data in Next.js is a fundamental skill for developers aiming to build dynamic, high-performance web applications. Next.js, a React-based framework, offers multiple methods to retrieve data both on the server and client side, enabling seamless rendering and improved user experience. Understanding how to fetch data effectively in Next.js is crucial, as it impacts SEO, page load

Nov 17, 2025 - 11:15
Nov 17, 2025 - 11:15
 0

Introduction

Fetching data in Next.js is a fundamental skill for developers aiming to build dynamic, high-performance web applications. Next.js, a React-based framework, offers multiple methods to retrieve data both on the server and client side, enabling seamless rendering and improved user experience. Understanding how to fetch data effectively in Next.js is crucial, as it impacts SEO, page load speed, and overall application reliability. This tutorial provides a comprehensive guide on how to fetch data in Next.js, covering practical steps, best practices, tools, real-world examples, and answers to common questions.

Step-by-Step Guide

1. Understanding Data Fetching Methods in Next.js

Next.js supports several data fetching techniques, each serving different use cases:

  • getStaticProps: Fetch data at build time for static site generation (SSG).
  • getServerSideProps: Fetch data on each request for server-side rendering (SSR).
  • getStaticPaths: Used with dynamic routes to generate static pages.
  • Client-side Fetching: Fetch data inside React components using hooks like useEffect.

2. Using getStaticProps for Static Generation

This method fetches data at build time and pre-renders pages with that data.

Example:

export async function getStaticProps() {

const res = await fetch('https://api.example.com/data')

const data = await res.json()

return {

props: {

data,

},

}

}

In your page component, access the data via props:

function Page({ data }) {

return (

<div>

<h1>Static Data</h1>

<pre>{JSON.stringify(data, null, 2)}</pre>

</div>

)

}

3. Using getServerSideProps for Server-Side Rendering

This method fetches data on every request, ideal for dynamic data that changes frequently.

Example:

export async function getServerSideProps() {

const res = await fetch('https://api.example.com/data')

const data = await res.json()

return {

props: {

data,

},

}

}

The page component will receive fresh data on each request.

4. Using getStaticPaths with Dynamic Routes

When you have dynamic routes, getStaticPaths lets you specify which pages to generate at build time.

Example:

export async function getStaticPaths() {

const res = await fetch('https://api.example.com/items')

const items = await res.json()

const paths = items.map(item => ({

params: { id: item.id.toString() },

}))

return { paths, fallback: false }

}

export async function getStaticProps({ params }) {

const res = await fetch(https://api.example.com/items/${params.id})

const item = await res.json()

return {

props: {

item,

},

}

}

5. Client-side Data Fetching with React Hooks

For parts of your application where data needs to update frequently or after page load, client-side fetching is appropriate.

Example using useEffect and useState:

import { useState, useEffect } from 'react'

function ClientSideFetch() {

const [data, setData] = useState(null)

const [loading, setLoading] = useState(true)

const [error, setError] = useState(null)

useEffect(() => {

async function fetchData() {

try {

const res = await fetch('https://api.example.com/data')

if (!res.ok) {

throw new Error('Network response was not ok')

}

const result = await res.json()

setData(result)

} catch (err) {

setError(err.message)

} finally {

setLoading(false)

}

}

fetchData()

}, [])

if (loading) return <p>Loading...</p>

if (error) return <p>Error: {error}</p>

return <pre>{JSON.stringify(data, null, 2)}</pre>

}

Best Practices

1. Choose the Right Data Fetching Method

Select getStaticProps for data that doesn’t change often to optimize performance and SEO. Use getServerSideProps for frequently changing or user-specific data. Client-side fetching is best for interactive or real-time updates after page load.

2. Handle Errors Gracefully

Always include error handling in your data fetching logic to improve user experience and debugging. Check HTTP response statuses and catch exceptions.

3. Optimize API Requests

Minimize the number of API calls by batching requests or caching data when possible. Use incremental static regeneration (ISR) with revalidate in getStaticProps to update static pages periodically.

4. Secure Sensitive Data

Never expose sensitive API keys or secrets in client-side code. Utilize server-side functions like API routes or environment variables for secure data handling.

5. Use TypeScript for Type Safety

Implement TypeScript interfaces for your data to prevent bugs and improve code maintainability.

6. Leverage SWR or React Query for Client-side Fetching

These libraries provide caching, revalidation, and other advanced features to simplify client-side data fetching.

Tools and Resources

1. Next.js Official Documentation

The official Next.js data fetching docs provide detailed explanations and examples.

2. SWR (Stale-While-Revalidate)

A React Hooks library for client-side data fetching developed by Vercel. It enables caching, revalidation, and better UX. Visit SWR Official Site.

3. React Query

Another powerful data-fetching library that supports caching, background updates, and more. Check out React Query Official Site.

4. Postman

A popular API client to test endpoints before integrating them into your Next.js app. Visit Postman.

5. REST and GraphQL APIs

Next.js can fetch data from any API type. Popular GraphQL clients include Apollo Client and Relay.

Real Examples

Example 1: Static Blog with getStaticProps

Imagine a blog where posts are fetched at build time from a CMS API.

export async function getStaticProps() {

const res = await fetch('https://api.examplecms.com/posts')

const posts = await res.json()

return {

props: { posts },

revalidate: 60, // ISR: regenerate page every 60 seconds

}

}

function Blog({ posts }) {

return (

<div>

<h1>Blog Posts</h1>

<ul>

{posts.map(post => (

<li key={post.id}>{post.title}</li>

))}

</ul>

</div>

)

}

Example 2: User Profile with getServerSideProps

Fetching user-specific data on each request for a profile page.

export async function getServerSideProps(context) {

const { userId } = context.params

const res = await fetch(https://api.example.com/users/${userId})

const user = await res.json()

return {

props: { user },

}

}

function UserProfile({ user }) {

return (

<div>

<h1>{user.name}</h1>

<p>Email: {user.email}</p>

</div>

)

}

Example 3: Client-side Fetching with SWR

import useSWR from 'swr'

const fetcher = url => fetch(url).then(res => res.json())

function LatestNews() {

const { data, error } = useSWR('https://api.example.com/news', fetcher)

if (error) return <div>Failed to load</div>

if (!data) return <div>Loading...</div>

return (

<ul>

{data.articles.map(article => (

<li key={article.id}>{article.title}</li>

))}

</ul>

)

}

FAQs

Q1: When should I use getStaticProps vs getServerSideProps?

Answer: Use getStaticProps when your data doesn’t change frequently and can be generated at build time for faster load and better SEO. Use getServerSideProps for data that must be fresh on every request or depends on user sessions.

Q2: Can I fetch data from external APIs in Next.js?

Answer: Yes, Next.js supports fetching data from any external API using the standard fetch API or third-party libraries like Axios.

Q3: How can I improve SEO when fetching data?

Answer: Fetch data on the server side using getStaticProps or getServerSideProps so that content is rendered in the HTML, making it crawlable by search engines.

Q4: Is client-side fetching bad for SEO?

Answer: Client-side fetching can negatively impact SEO because content loads after the initial HTML rendering. Use server-side fetching for critical SEO content.

Q5: How can I handle loading and error states during client-side fetching?

Answer: Use React state to track loading and error statuses. Display appropriate UI feedback, such as spinners or error messages, to improve user experience.

Conclusion

Fetching data in Next.js is a versatile process that can be tailored to your application's needs by selecting the appropriate method: static generation, server-side rendering, or client-side fetching. Mastering these techniques is essential for building fast, SEO-friendly, and user-centric web applications. By following best practices, leveraging powerful tools like SWR or React Query, and understanding real-world examples, developers can efficiently integrate data fetching into their Next.js projects. Whether you are building a blog, user dashboard, or e-commerce site, Next.js provides robust solutions to meet your data fetching requirements.