SWR is one of the best libraries I have ever used

March 22, 2020

The more I use this library, the more I fall in love with it. I think it comes down to how simple it is, with just one main way to interact with the API (the useSWR hook), that progressively discloses more and more features as you use it.

In the simplest form you can use the library to fetch some data:

const { data: books } = useSWR("/api/books");

Need to fetch something based on some other value? They thought of that too:

const { bookId } = props;
const { data: book } = useSWR(() => bookId && `/api/book/${bookId}`);

If bookId is not there, this fetches nothing and book will be null, as you would expect.

Need to handle errors? You guessed it, it’s just another destructuring away:

const { error } = useSWR("/api/books");

I have been using this library for Mailbrew, and months into using it I keep discovering new useful features. For example, I just discovered that you can mutate data in the local cache to implement optimistic updates. I plan to do that soon and replace our custom implementation of this that uses Redux.

Fetchers

Another cool thing is the concept of fetcher. By default when used with just one parameter useSWR fetches the data using window.fetch. You can customize the fetcher to use your own, in the case of Mailbrew, we use an axios with the correct authentication headers set.

This is really easy to do, just define a fetcher function:

export const axiosSwrFetcher = async (query) => (await axios.get(query)).data;

And pass it as second parameter, in your useSWR calls:

const { data: books } = useSWR("/api/books", axiosSwrFetcher);

Or change the defaults at the app level:

<SWRConfig value={{ fetcher: axiosSwrFetcher }}>
  <App />
</SWRConfig>

The complexity behind the simplicity

Another incredibly cool thing about SWR is that, even by just using the simplest example at the top of this post, you get a ton of functionality for free, things that make your app actually better for your user:

  • caching — your app uses cached data while fetching new one (this is actually what SWR stands for, stale-while-revalidate)
  • refresh data when window regains focus, so your user don’t risk manipulating outdated data and syncing it back to the server
  • refresh data on reconnect, when a disconnected device goes back online
  • retry on error — in case of an error fetching the data, useSWR retries after a while

This is the default behavior, you can customize all of is and access other useful settings via the configuration.

Conclusion

I am excited to see where this goes, especially with Suspense coming to React soon.