Introduction to SWR

SWR is an all-new data fetching library made by the team at ZEIT, the same team that created Now and Next.js.

This new library is made specifically for React applications as a custom hook with a straightforward interface.

Let's build a small project using SWR and Next.js to see how it works.

Running Demo

This is the final project running in CodeSandbox

<iframe src="https://codesandbox.io/embed/hello-world-l6zmc?fontsize=14&hidenavigation=1&theme=light&view=preview" style="width:100%;height:500px;border:0;border-radius:4px;overflow:hidden;" title="Introduction to SWR" allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"

</iframe>

Setup Project

First, let's create the project.

npx create-next-app

This will give us a basic Next.js application after writing the name we want for it.

Now let's install SWR and isomorphic-unfetch, this one will help us do the fetch.

yarn add swr isomorphic-unfetch

And that's all if we run our project with yarn dev we will already have a page with some components, we could safely delete them since we are not going to use them.

The API

The API we will consume in our application is Pokeapi, this free API will give use endpoints to get information about different Pokémon.

The Initial Page

Let's start coding, first, we need to create a file pages/index.js where we will export a React component, this will be our home page.

import Head from "next/head";
import useSWR from "swr";
import fetcher from "../lib/fetcher";

function HomePage() {
  const { data } = useSWR("https://pokeapi.co/api/v2/pokemon", fetcher);

  if (!data) return <h1>Loading...</h1>;
  const { results } = data;

  return (
    <>
      <Head>
        <link
          href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css"
          rel="stylesheet"
        />
      </Head>

      <section className="container mx-auto">
        <div className="-mx-2 flex flex-wrap">
          <article key={results[0].name}>{results[0].name}</article>
        </div>
      </section>
    </>
  );
}

export default HomePage;

Note: We are using Tailwind here to have some basic styles, this is not the best way to load Tailwind in a real-world application.

Fetcher

Our fetcher above is a simple module that will run the fetch and reply with the JSON data instead of the HTTP response.

import fetch from "isomorphic-unfetch";

function fetcher(...args) {
  return fetch(...args).then((response) => response.json());
}

export default fetcher;

A Better List of Pokémon

With this we have a list of the first 20 Pokémon names, let's create a new component to show more information about each one.

import fetcher from "../lib/fetcher";
import useSWR from "swr";

function PokemonShort({ name }) {
  const { data } = useSWR(`https://pokeapi.co/api/v2/pokemon/${name}`, fetcher);

  return (
    <div className="my-5 p-2 w-1/3">
      <article className="shadow p-5 relative">
        <h2 className="font-bold text-xl capitalize">{name}</h2>
        {data ? (
          <>
            <div className="absolute top-0 right-0">
              <img src={data.sprites.front_default} />
            </div>
            <ul>
              <li>
                <strong>Weight</strong>: {data.weight}
              </li>
              <li>
                <strong>Height</strong>: {data.height}
              </li>
            </ul>
            <br />
            <h3 className="font-bold text-lg">Stats</h3>
            <ul className="flex justify-start items-baseline flex-wrap">
              {data.stats.map((stat) => (
                <li key={stat.stat.name} className="w-3/6">
                  <strong className="capitalize">{stat.stat.name}</strong>:{" "}
                  {stat.base_stat}
                </li>
              ))}
            </ul>
          </>
        ) : (
          <p className="font-bold text-l capitalize">Loading {name}...</p>
        )}
      </article>
    </div>
  );
}

export default PokemonShort;

Here we will show the Pokémon name since the beginning and only show the loading text until we have the stats, measures and sprite URL.

Now on our HomePage, we need to import and use PokemonShort.

import Head from "next/head";
import useSWR from "swr";
import fetcher from "../lib/fetcher";
import PokemonShort from "../components/pokemon-short";

function HomePage() {
  const { data } = useSWR("https://pokeapi.co/api/v2/pokemon", fetcher);

  if (!data) return <h1>Loading...</h1>;
  const { results } = data;

  return (
    <>
      <Head>
        <link
          href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css"
          rel="stylesheet"
        />
      </Head>
      <section className="container mx-auto">
        <div className="-mx-2 flex flex-wrap">
          {results.map((result) => (
            <PokemonShort key={result.name} name={result.name} />
          ))}
        </div>
      </section>
    </>
  );
}

export default HomePage;

Now we should see a list of cards with the data of each Pokémon.

Our Next.js + SWR Pokedex Application

With this, we saw how to use SWR to fetch a list of data and then render a component per item and fetch more data inside them.

In future articles, I will continue working on this application and add more features.