DEV Community

Cover image for "useSWR" - React Hooks for Remote Data Fetching
Sung M. Kim
Sung M. Kim

Posted on

"useSWR" - React Hooks for Remote Data Fetching

Image by analogicus from Pixabay

Zeit has released a React hook, useSWR, which has a tag-line, "React Hooks for Remote Data Fetching".

SWR stands for, well, check out the site to see what it means (😉).

It does what it claims to do, and do it well and easily.

"Well"

useSWR boasts following features.

  • Lightweight
  • Backend agnostic
  • Realtime
  • JAMstack oriented
  • Suspense
  • TypeScript ready
  • REST compatible
  • Remote + Local

"Easy"

Suspense

Yes. It works with the experimental channel of React's Suspense.

All you need is to set the suspense: true as one of the options in the API.

  const { data } = useSWR(
    "https://jsonplaceholder.typicode.com/posts",
    url =>
      fetch(url)
        .then(_ => _.json())
        .then(sleep),
    { suspense: true }
  );

Fetching data.

Home page shows the following basic example.

import useSWR from '@zeit/swr'

function Profile () {
                                               1️⃣ 👇
  const { data, error } = useSWR('/api/user', fetch)

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}

In this example, the React Hook useSWR accepts a key and a fetch function. key is a unique identifier of the data, normally the URL of the API. Then key will be passed to fetch, which returns the data asynchronously.

I was kind of lost with 1️⃣ fetch as I was expecting to pass fetch and expected useSWR to auto convert the response to a json string as axios does but it doesn't.

So using the pattern in the basic example, you might want to pass your own method, which fetches data, and transforms it into a json (refer to getRandomDog method below).

const getRandomDog = url => fetch(url).then(_ => _.json());

// https://swr.now.sh/#basic-data-loading
function BasicDataLoading() {
  const { error, data } = useSWR(
    `https://dog.ceo/api/breeds/image/random`,
    getRandomDog
  );

  return (
    <>
      {error && <p>Error! {error}</p>}
      {data && data.status === "success" && (
        <img src={data.message} alt={data.message} />
      )}
    </>
  );
}

I found it to work like a function, which accepts the key ('/api/user' in the basic example) and "you" as a caller decide how to return a value. Be it an async method, or synchronous method, it didn't matter when I tried.

const getCachedText = async text => text;
const options = {
  revalidateOnFocus: false,
  shouldRetryOnError: false
};
function CachedHeader() {
  const { data: cachedText } = useSWR("Cached Header", getCachedText, options);

  return <h1>{cachedText}</h1>;
}

function Identity({ value }) {
  const { data } = useSWR(value, () => value, options);

  return <>{data}</>;
}

Sandbox

I've created a sandbox to play around & learn the library.

Fork it and play around :)

Note: It uses an experimental version of React (it can break anytime)

Parting Words

This post is created within an hour just to log & share the excitement 🎉

Check out the project page, https://swr.now.sh/ to learn more and learn more on the GitHub repo, https://github.com/zeit/swr.

Top comments (12)

Collapse
 
nickytonline profile image
Nick Taylor

Thanks sharing Sung. Gonna take a look at this when I get a chance. Between this and restful-react, all kinds of great stuff out there right now.

GitHub logo contiamo / restful-react

A consistent, declarative way of interacting with RESTful backends, featuring code-generation from Swagger and OpenAPI specs 🔥

restful-react

Building React apps that interact with a RESTful API presents a set of questions, challenges and potential gotchas. This project aims to remove such pitfalls, and provide a pleasant developer experience when crafting such applications. It can be considered a thin wrapper around the fetch API in the form of React components and hooks.

As an abstraction, this tool allows for greater consistency and maintainability of dynamic codebases.

Overview

At its core, restful-react exposes a hook, called useGet. This component retrieves data, either on mount…

Collapse
 
dance2die profile image
Sung M. Kim

You're welcome, Nick and thanks for sharing restful-react.

There are many good libraries out there still yet undiscovered and we don't know about :)

Collapse
 
rohansawant profile image
Rohan Sawant

You Go Sung! 🔥

Collapse
 
dance2die profile image
Sung M. Kim

Thanks Rohan. Glad to see ya on DEV :)

Collapse
 
thejoezack profile image
Joe Zack

I'm a total React noob, but I would normally do this with useEffect. Is the main benefit the support for suspense?

Collapse
 
thejoezack profile image
Joe Zack

Ah, I think I see after playing with your example. It's nice to have it remote/local friendly out of the box. Thanks!

Collapse
 
dance2die profile image
Sung M. Kim

As I am also a noob at useSWR, I just tried to explain as much as I know :p

I would normally do this with useEffect

Yes. One would normally use useEffect by default to fetch data (as it's a side effect).

useSWR would ease the burden of having to write much boilterplate code.

useSWR is using useLayoutEffect over useEffect (, which I'd like to know the reason behind it).

github.com/zeit/swr/blob/a323fa702...

thinking out loudly:

Maybe this article by Dave Ceddia would provide an answer.

When to useLayoutEffect Instead of useEffect

Is the main benefit the support for suspense?

It's only one of the nice features :)

The main benefit is hidden in the name, SWR

SWR first returns the data from cache (stale), then sends the fetch request (revalidate), and finally comes with the up-to-date data again.

Basically not showing "loading" screen as soon as a data is being fetched/refetched.

That sounds a bit like Pending → Skeleton → Complete Concurrent UI pattern in the experimental channel (but not sure if they are the same).

You can also do optimisitic UI update using mutate, meaning, you can show updated state right away before getting remote data. And revert if the change was not made.

Collapse
 
ntvinhit profile image
Nguyễn Trọng Vĩnh

useAsync, useAsyncRetry and useAsyncFn is better!

Change my mind!

Collapse
 
dance2die profile image
Sung M. Kim • Edited

No, I won't change your mind 🙂

On the other hand, as this post touched good parts of useSWR, I will share a nice/thorough concerns (by Sébastien Lorber) one should watch out for.

Sébastien is an author of github.com/slorber/react-async-hook, which is in works to be merged with React-Async.

reddit.com/r/reactjs/comments/dof4...

Collapse
 
roeljohn profile image
Roel John Bobis

This is AWESOME!!!!!!!!!

Collapse
 
dance2die profile image
Sung M. Kim

Thanks, Roel~

Collapse
 
keiji009 profile image
keiji009

I 'd like to ask how to useSRW get request from graphql service.