blogsaboutContactPrivacy PolicyTerms & Conditions
NextJsnextjs_swr

Data Fetching in Next.js Using SWR - A Complete Guide

April 13, 2025

24 min read

420 views

Introduction

In modern web development, optimize data fetching is at the core of building fast, interactive, and user-friendly applications. Whether you're pulling data from an API, a CMS, or a custom backend, handling the flow of data properly is essential - especially in frameworks like Next.js, which offers both server-side and client-side rendering options.

Learn More About Server Side Rendering in Next.js

While Next.js provides built-in methods like getServerSideProps and getStaticProps for server-side data fetching, there are situations where client-side fetching is more appropriate — especially when you need features like real-time updates, caching, and auto revalidation.

That's where SWR comes in.

Developed by Vercel (the team behind Next.js), SWR stands for Stale-While-Revalidate - a strategy that prioritizes speed and user experience by serving cached data instantly while revalidating in the background. It's a lightweight and powerful React hook for data fetching, perfect for use in Next.js applications.

What is SWR?

SWR stands for Stale-While-Revalidate, a modern data fetching strategy that improves the user experience by serving cached (stale) data instantly while revalidating it in the background. This means your users see data immediately while newer data is fetched quietly and updated without a full page reload.

Key Features of SWR:

  • Cache-first fetching strategy (fast UI load)
  • Automatic revalidation when the window regains focus or reconnects to the network
  • Built-in caching, pagination, and real-time updates
  • Configurable behavior through a global \<SWRConfig> provider
  • Lightweight (small bundle size) compared to alternatives like React Query

Learn More About React Query

Installing SWR

Setting up SWR in Next.js project is simple and straightforward. Since SWR is a lightweight React hook library, you can install it directly via your package manager of choice - no complex configuration needed.

Installation Command

.ssh
1npm install swr

you can also use Yarn or pnpm if you prefer.

Once installed, you can immediately start using the useSWR hook in Next.js to fetch data.

Basic Usage of useSWR Hook in Next.js

Once SWR is installed, the core of using it comes down to one powerful and easy-to-use hook: useSWR.

The useSWR hook takes two main arguments:

  1. A key (usually the URL or unique identifier for the request)

  2. A fetcher function (used to actually fetch the data)

Minimal Example: Fetching Data from an API

Here's a basic example of how to fetch user data using SWR in Next.js and the fetch API:

.jsx
1  "use client";
2import useSWR from 'swr';
3
4// Fetcher function
5const fetcher = (url) => fetch(url).then((res) => res.json());
6
7export default function User() {
8const { data, error, isLoading } = useSWR('https://jsonplaceholder.typicode.com/users/1', fetcher);
9
10if (isLoading) return <div>Loading...</div>;
11if (error) return <div>Failed to load user</div>;
12
13return (
14  <div>
15    <h2>{data.name}</h2>
16    <p>Email: {data.email}</p>
17  </div>
18);
19}
20

In Next.js App Router, all components are React Server Components (RSC) by default. You could only import the key serialization APIs from SWR in RSC.

.jsx
1import { unstable_serialize } from 'swr' // ✅ Available in server components
2import { unstable_serialize as infinite_unstable_serialize } from 'swr/infinite' // ✅ Available in server components

You can mark your components with 'use client' directive or import SWR from client components, both ways will allow you to use the SWR client data fetching hooks.

Advantages of This Approach

  • No need to manage loading or caching logic manually.
  • The UI updates automatically when fresh data is revalidated.0
  • You can easily swap in your own HTTP client (e.g., Axios) if needed.

With Axios (Alternative)

If you prefer Axios instead of fetch, use axios in fetcher function:

.jsx
1  "use client";
2import useSWR from 'swr';
3import axios from 'axios';
4
5const fetcher = (url) => axios.get(url).then((res) => res.data);
6.....

Caching and Revalidation in SWR

One of the key strengths of SWR is its intelligent caching and revalidation strategy. These features ensure your data stays fresh without requiring extra code — providing both speed and up-to-date content.

How Caching Works

SWR caches responses in memory based on the key you provide (usually the URL). When a component using useSWR mounts, SWR checks if the data is already cached:

  • If yes, it returns the cached (stale) data instantly.

  • Then, it sends a request in the background to revalidate and fetch fresh data.

  • When the fresh data is returned, SWR updates the cache and re-renders the component.

This strategy is known as stale-while-revalidate, hence the name SWR.

Revalidation Triggers

SWR automatically revalidates data under several conditions:

  • On mount: Revalidates the data when the component loads
  • On window focus: Fetches fresh data when the browser window gains focus (great for tab switching)
  • On network reconnect: Re-fetches when the user comes back online
  • Manually: You can trigger revalidation using the mutate function

Customizing Revalidation Behavior

You can customize how often or when data is revalidated:

.jsx
1const { data } = useSWR('/api/data', fetcher, {
2revalidateIfStale: true, // Revalidate even if cached data exists
3revalidateOnMount: true, // Revalidate when component mounts
4revalidateOnFocus: false, // Disable revalidation on window focus
5refreshInterval: 0, // Disable polling (set to 5000 for 5s refresh)
6});

Clearing or Mutating the Cache

SWR exposes utility functions to manually mutate or clear the cache:

.jsx
1const { mutate } = useSWRConfig();
2
3// Re-fetch data for a specific key:
4mutate('/api/user'); 
5
6// Update cache instantly (optimistic UI):
7mutate('/api/user', newUserData, { revalidate: false });

By understanding these SWR caching and revalidation features, you can improve both performance and user experience in your Next.js apps.

Pagination with SWR

When dealing with large datasets like blog posts, products, or user lists, loading everything at once can slow down your app. Pagination helps break the data into chunks, improving both performance and user experience.

SWR doesn't come with built-in pagination UI, but it makes client-side pagination and infinite scrolling easy to implement by combining useSWR with dynamic keys and conditional fetching.

Basic Pagination Example

Here's how to implement basic pagination using SWR:

.jsx
1 "use client";
2import { useState } from 'react';
3import useSWR from 'swr';
4
5const fetcher = (url) => fetch(url).then(res => res.json());
6
7export default function PaginatedPosts() {
8const [page, setPage] = useState(1);
9const { data, isLoading, error } = useSWR(`https://jsonplaceholder.typicode.com/posts?_limit=5&_page=${page}`, fetcher);
10
11if (isLoading) return <p>Loading...</p>;
12if (error) return <p>Failed to load data</p>;
13
14return (
15  <div>
16    <h2>Page {page}</h2>
17    <ul>
18      {data.map(post => (
19        <li key={post.id}>
20          <strong>{post.title}</strong>
21          <p>{post.body}</p>
22        </li>
23      ))}
24    </ul>
25
26    <div>
27      <button onClick={() => setPage(p => Math.max(p - 1, 1))} disabled={page === 1}>
28        Previous
29      </button>
30      <button onClick={() => setPage(p => p + 1)}>
31        Next
32      </button>
33    </div>
34  </div>
35);
36}
37

How It Works:

  • You update the page state when the user clicks Next or Previous.
  • SWR fetches a new URL with the updated page number.
  • Each page's response is cached individually.

With just a few lines of code, SWR helps you create fast, dynamic, and user-friendly pagination in your Next.js apps.

Common Errors and Troubleshooting

While SWR simplifies data fetching, developers—especially those new to it—can still encounter a few common issues. Below are the most frequent errors along with explanations and solutions to fix them effectively.

  1. TypeError: Failed to fetch

This usually occurs when the fetcher function can't reach the API endpoint.

Possible Reasons:

  • Incorrect API URL
  • Server not running
  • Network issues or CORS problems

Solution:

  • Double-check the endpoint URL

  • Use tools like Postman or your browser to test the API directly

  • If using a local API, ensure the server is running

  • For CORS issues, enable appropriate headers on the server

  1. data is undefined

You're trying to use the data before it's available.

Solution:

Always include loading and error states in your component:

.jsx
1const { data, error, isLoading } = useSWR('/api/posts', fetcher);
2
3if (isLoading) return <p>Loading...</p>;
4if (error) return <p>Failed to load</p>;
  1. Unhandled API Errors

By default, SWR won't throw fetch errors—you need to check error in the response object.

Improve error detection inside your fetcher:

.jsx
1const fetcher = async (url) => {
2const res = await fetch(url);
3if (!res.ok) {
4  throw new Error('An error occurred while fetching the data.');
5}
6return res.json();
7};
8

Debugging Tips

  • Use console.log() in your fetcher to track API calls

  • Wrap your UI with loading and error states

  • Try SWR Devtools for debugging cache and requests visually

By understanding these issues and knowing how to resolve them, you'll be better prepared to build robust and error-resilient features using SWR.

Frequently Asked Questions

  • Q: What does SWR stand for?

    A: SWR stands for “Stale-While-Revalidate,” a caching strategy that serves stale data while revalidating in the background for up-to-date results.

  • Q: Do I need SWR if I'm already using getServerSideProps or getStaticProps?

    A: Those Next.js functions are great for static and server-side rendering. SWR complements them by providing client-side data fetching after the initial page load.

  • Q: How do I stop SWR from refetching when the window regains focus?

    A: Pass the option revalidateOnFocus: false to your useSWR hook or set it globally via SWRConfig.

Conclusion

SWR is a powerful and lightweight React hook library that brings simplicity and performance to client-side data fetching in Next.js applications. With built-in features like caching, revalidation, and automatic updates on focus or reconnect, it allows you to build fast and reactive UIs with minimal code.

In this guide, you learned how to install and use SWR, fetch data from external APIs, handle caching and pagination, and troubleshoot common issues. Whether you're building a dashboard, blog, or any data-driven app, SWR is an excellent tool to keep your UI and data in sync—efficiently and effortlessly.

Now that you understand the basics and advanced patterns, start using SWR in your projects and see how it transforms your data-fetching workflow!

If you found this article helpful, feel free to share it with others who may benefit from it!

Share this article

On this page: