How to Use the SWR Library for Better Data Fetching in React
[ad_1]
React is un-opinionated about how you fetch and manage the remote data in your application.
You may think of using the useEffect
hook for simple fetching operations, but it will not help you with caching, request deduplication, always serving real-time data, and so on.
Things will get more complicated when you try to implement them by yourself. But fortunately, the SWR library helps us solve some common problems and it also simplifies development.
What is the SWR Library?
According to the SWR documentation:
The name “SWR” is derived from
stale-while-revalidate
, a HTTP cache invalidation strategy popularized by HTTP RFC 5861.SWR is a strategy to first return the data from cache (stale), then send the fetch request (revalidate), and finally come with the up-to-date data.
With the help of this strategy, you can make sure to always display up-to-date data to your users.
So, SWR is a library built upon the stale-while-revalidate
strategy, and it provides React hooks for data fetching.
Before moving on to the details, let’s look at the two most important concepts of SWR.
Caching
A cache stores data for a specified amount of time and serves this data to users who request it within that period of time.
The time can be a certain period like 5000ms
or can be an event like re-connecting to the Internet.
SWR automatically caches the fetched data, helping to quickly serve the data without making redundant network requests.
Revalidation
When the valid time is exceeded, the data becomes stale. When a user requests this data you should revalidate it before serving it.
If the data is stale, SWR revalidates it (re-fetches from the server) to keep it fresh.
By default, SWR automatically revalidates the data (it assumes that the data is stale) in three cases:
- Every time the component is mounted, even if there is data in the cache, it revalidates.
- It revalidates when the window gets focused.
- It revalidates when the browser regains its network connection.
How to Use the useSWR
Hook
The useSWR
hook is the main hook of the library. In your projects, you’ll almost always use this hook.
It accepts three parameters: key
, fetcher
, and options
.
key
is a unique string for the request like an id.fetcher
is an async function that accepts thekey
and returns thedata
. SWR automatically passes thekey
to thefetcher
function when loading the data.options
is an object of options available for the hook. For example, you can specify the cache time in theoptions
object.
And it returns an object with data
, error
, isValidating
, isLoading
, and mutate
properties.
data
is the variable returned from thefetcher
function. During the first request, it will beundefined
.error
is the error thrown by thefetcher
function. If there is no error, it will beundefined
.isLoading
is a boolean that indicates the first request’s status. It istrue
during the first request, and it will always befalse
thereafter.isValidating
is also a boolean that indicates the request’s status. It istrue
during each request including the first one.mutate
is a function for manually triggering a revalidation.
How I Used SWR in My Project
The best thing about SWR is how easy it is to use. I tried out it in my first project for the Front End Libraries Certification of freeCodeCamp and liked it very much.
I used TypeScript for the project, but will give you examples with JavaScript. So, don’t worry if you don’t know TypeScript – I highly recommend giving it a try if you haven’t yet.
Also, if you are interested, you can find the project’s code in its GitHub repository.
How to Add the swr
Dependency to the Project
To be able to use the library, you can install it via npm
, pnpm
, or yarn
. I prefer using pnpm
as the package manager for my project.
$ npm i swr
# or
$ pnpm add swr
# or
$ yarn add swr
Create the fetcher
Function
The goal of this function is to fetch the data by URL and return it. I will use the function with SWR.
const fetcher = async (url) => {
const { data } = await axios.get(url);
return data;
};
The fetcher
function:
- accepts a
url
parameter, - fetches the data with the
get
method of Axios, - returns the
data
returned from the request.
Create a Hook That Fetches a Random Quote
Based on the SWR documentation, I created a hook called useRandomQuote
. This hook is a wrapper for the useSWR
hook. Thus, I can use the same data wherever needed.
import useSWR from 'swr/immutable';
const useRandomQuote = () => {
const { data, ...restSWR } = useSWR(
'https://api.quotable.io/quotes/random',
fetcher
);
return {
...restSWR,
quote: data?.[0],
};
};
export { useRandomQuote };
The hook fetches the data with useSWR
and returns an object that contains the variables destructured from the useSWR
hook and the quote
property which is the only element in the returned array. I used the Quotable API for a random quote, and the API returns an array with one element which is the random quote.
If you noticed, I imported the useSWR
hook from swr/immutable
in the code snippet. It is auto-revalidation disabled version of the hook. I prefer to use it because I want to revalidate the data manually with the mutate
function.
How to Revalidate the Data Manually
If you want to manually revalidate the data, you can use the mutate
function returned from the useSWR
hook.
When the mutate function is called, SWR revalidates the data. During this process, the data
variable remains the same (will not be undefined), and the isValidating
variable becomes true.
The following diagram from the SWR documentation visualizes the revalidation process:
In my project, I have a QuoteCard
component that displays the current quote. This component has a New Quote
button that triggers retrieving a new random quote.
const QuoteCard = () => {
const { /* ... */, mutate } = useRandomQuote();
return (
{/* ... */}
<button
// ...
onClick={() => mutate()}
>
New Quote
</button>
{/* ... */}
)
}
In the code above, I used the mutate
function in the onClick
handler of the New Quote
button.
How to Handle Concurrent Requests
If the user initiates a new request alongside the ongoing one, this results in multiple concurrent requests. Each request waits for the previous one to complete before starting the process, resulting in unnecessary network usage and waiting time.
I faced the same issue in my project. When the user clicks the New Quote
button while a request is still loading, the application triggers a new request alongside the existing one.
As you see in the GIF above, when I click the “New Quote” button consecutively, I have to wait for all requests to be done to see a random quote because SWR only updates the data after the last request is completed.
As a result, I should cancel the ongoing previous request after a new request is initiated. Although I checked SWR’s documentation, I couldn’t find a built-in solution for this issue. I tried to use AbortController
with SWR, but couldn’t succeed.
As a workaround, I disabled the New Quote
button during validation to be able to prevent multiple concurrent requests.
A little note: I also checked React Query, and it has a built-in solution for that. I am planning to experiment with it in my next project involving remote data.
Conclusion
React doesn’t care how you fetch and manage remote data. In this tutorial, you have learned how to do this with SWR. Although it has a big drawback regarding canceling concurrent requests, you can usually work around this and benefit from its upsides.
If you haven’t used SWR before, I highly recommend trying it out in your future projects. It saves you time and prevents you from experiencing many types of bugs.
Thank you for reading. You can connect with me on Twitter or explore more on my personal website. Feel free to reach out — I’d love to hear from you!
[ad_2]
Source link