DEV Community

David Quick
David Quick

Posted on

Data fetching with SWR in React

SWR is a library that provides React Hooks for data fetching. It's made by ZEIT, the folks over at Next.js and allows you to pre-fetch your data on the client side while using http caching.

There are a lot of amazing features that come with SWR, but we'll be focusing on the basics. If you'd like to learn more, you can head over to the SWR page.

Getting Started

I've created a very basic skeleton to work with over at Codesandbox. You can use it to follow along.

I have gone ahead and added swr as a dependency and imported it in the main App component.

Using SWR

In our App.js file lets call the useSWR hook right above our return() statement:


  const { data, error } = useSWR(key, fetcher);

Enter fullscreen mode Exit fullscreen mode

Above, we're using object destructuring with a data and error variable:

  • data: The data returned from the fetcher
  • error: The error provided

When calling useSWR(), we see that it take in two arguments:

  • key: The URL for the API endpoint or path if your data is local.
  • fetcher: A function that retrieves data from an API request.

In the case of our fetcher, we'll be using the fetch API. You can use any fetching library you feel most comfortable with. useSWR has no mandatory preference to how the data is fetched.

The API and Fetcher Function

For this article, we'll be using the Jikan API to fetch a list of top airing Anime titles.

The following code will be placed above our useSWR() call.

Let's start by storing our API endpoint in a variable:

  const url = 'https://api.jikan.moe/v3/top/anime/1/airing';
Enter fullscreen mode Exit fullscreen mode

Now, we can go ahead and create our fetcher function:

  const fetcher = (...args) => fetch(...args).then(res => res.json());
Enter fullscreen mode Exit fullscreen mode

The fetcher function above takes in all of our arguments using the spread operator and calls fetch. It may not seem obvious, but the arguments being spread is the url for our API. Fetch returns a promise so we use .then() to get the response and turn it into JSON.

Our component should now look like this:

import React from "react";
import "./styles.css";

import useSWR from 'swr';

export default function App() {
  const url = 'https://api.jikan.moe/v3/top/anime/1/airing';
  const fetcher = (...args) => fetch(...args).then(res => res.json());

  const { data, error } = useSWR(url, fetcher)

  console.log(data.top) 

  return (
    <div className="App">
      <h1>Fetching data with SWR</h1>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

If we do a quick console log of our data as I've added above, we should see our fetched data with 50 objects.

I've used data.top as it's the exact endpoint to display our data.

The response for the first object should look something like this:

mal_id: 40591
rank: 1
title: "Kaguya-sama wa Kokurasetai?: Tensai-tachi no Renai Zunousen"
url: "https://myanimelist.net/anime/40591/Kaguya-sama_wa_Kokurasetai__Tensai-tachi_no_Renai_Zunousen"
image_url: "https://cdn.myanimelist.net/images/anime/1764/106659.jpg?s=aab19d0f19e345e223dc26542ac3a28f"
type: "TV"
episodes: null
start_date: "Apr 2020"
end_date: null
members: 164557
score: 8.8
Enter fullscreen mode Exit fullscreen mode

If the title and result isn't exactly the same, no worries. The data received is top airing anime, so this could change depending on when you read this article.

The only thing left is to add quick error handling and to display some sort of notification in the event that the data doesn't load immediately. We can add the following to our existing code:

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
Enter fullscreen mode Exit fullscreen mode

The above is pretty self explanatory, but we are simply saying if there is an error, then display "failed to load" and if there is no data, return "loading...".

Our full component should now look like this:

import React from "react";
import "./styles.css";

import useSWR from 'swr';

export default function App() {
  const url = 'https://api.jikan.moe/v3/top/anime/1/airing';
  const fetcher = (...args) => fetch(...args).then(res => res.json());

  const { data, error } = useSWR(url, fetcher)

  if (error) return <div>failed to load</div>;
  if (!data) return <div>loading...</div>;

  return (
    <div className="App">
      <h1>Fetching data with SWR</h1>
    </div>
  );
}


Enter fullscreen mode Exit fullscreen mode

We've successfully fetched our data using the useSWR hook!

Displaying the data

There's no use in having our data logged out to the console. We can quickly display our data by mapping over our data and displaying the title, image, and score:

import React from "react";
import "./styles.css";

import useSWR from 'swr';

export default function App() {
  const url = 'https://api.jikan.moe/v3/top/anime/1/airing';
  const fetcher = (...args) => fetch(...args).then(res => res.json());

  const { data, error } = useSWR(url, fetcher)

  if (error) return <div>failed to load</div>;
  if (!data) return <div>loading...</div>;

  return (
    <div className="App">
      <h1>Fetching data with SWR</h1>
      <div>
        {data.top.map((anime) => {
          return (
            <div key={anime.mal_id}>
              <h2>{anime.title}</h2>
              <img src={anime.image_url} alt='poster'/>
              <p>{anime.score}</p>
            </div>
          )
        })}
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Here's what our final project looks like:

Further learning

This article came about as I was working on a Next.js project and found using swr to be an ideal tool for said project. I decided to write this article specifically using React as it reaches a broader audience.

In the event you are using Next.js, I would highly recommend watching this video. It provides an in depth look at the useSWR hook and more of its features.

Top comments (2)

Collapse
 
sergiodxa profile image
Sergio Daniel Xalambrí

Tip: don’t create the fetcher inside the component, instead create it one time outside.

Collapse
 
papabearcodes profile image
David Quick

Thank you for the tip! This was just a quick overview. I usually do and would use the SWRConfig provider to pass in the fetcher and any other options. I just didn't think it was mandatory for the article.