• 18-19 College Green, Dublin 2
  • 01 685 9088
  • info@cunninghamwebsolutions.com
  • cunninghamwebsolutions
    Cunningham Web Solutions
    • Home
    • About Us
    • Our Services
      • Web Design
      • Digital Marketing
      • SEO Services
      • E-commerce Websites
      • Website Redevelopment
      • Social Media Services
    • Digital Marketing
      • Adwords
      • Social Media Services
      • Email Marketing
      • Display Advertising
      • Remarketing
    • Portfolio
    • FAQ’s
    • Blog
    • Contact Us
    MENU CLOSE back  

    An Introduction To SWR: React Hooks For Remote Data Fetching

    You are here:
    1. Home
    2. Web Design
    3. An Introduction To SWR: React Hooks For Remote Data Fetching
    fetching

    An Introduction To SWR: React Hooks For Remote Data Fetching

    An Introduction To SWR: React Hooks For Remote Data Fetching

    Ibrahima Ndaw

    2020-06-22T12:00:00+00:00
    2020-06-22T12:34:07+00:00

    SWR is a lightweight library created by Vercel (formerly ZEIT) that allows fetching, caching, or refetching data in realtime using React Hooks. It’s built with React Suspense which lets your components “wait” for something before they can render, including data. SWR ships also with great features such as dependent fetching, focus on revalidation, scroll position recovery, and so on. It’s also a very powerful tool since it’s backend agnostic and has good support for TypeScript. It’s a package that has a bright future.

    Why should you care? You should care if you’ve been looking for a library that does not only fetch data from APIs but also make it possible to do things like caching and dependent fetching. What will be covered in this tutorial will come in handy when building React applications with a lot of moving parts. It’s expected that you should have made use of Axios and the Fetch API, even though we’ll compare how they differ from SWR, we won’t be going into details on how they’ll be implemented.

    In this guide, I will introduce you to React Hooks for Remote Data Fetching by building a Pokedex app that requests data from the Pokemon API. We will also dive into other features that come with SWR as well, and highlight its differences compared to popular solutions such as the Fetch API and the Axios library and give you the reasons why using this library and why you should keep an eye on SWR.

    So, let’s start by answering a fundamental question: What is SWR?

    What Is SWR?

    SWR is an initialism of stale-while-revalidate. It’s a React Hooks library for remote data fetching. SWR works with three main steps: first, it returns the data from the cache (the stale part), then sends the fetch request (the revalidate part), and finally comes with the up-to-date data. But no worries, SWR handles all these steps for us. The only thing we have to do is give the useSWR hook the needed parameters to make the request.

    SWR has also some nice features such as:

    • Back-end agnostic
    • Fast page navigation
    • Revalidation on focus
    • Interval polling
    • Request deduplication
    • Local mutation
    • Pagination
    • TypeScript ready
    • SSR support
    • Suspense mode
    • React Native support
    • Lightweight.

    Sounds magical? Well, SWR simplifies things and increases for sure the user experience of your React app. And once we start implementing it in our project, you will see why this hook is handy.

    It’s important to know that the name of the package is swr or SWR and the hook used to get SWR features is named useSWR.

    In theory, the SWR is maybe what you need to enhance your data fetching. However, we already have two great ways of making HTTP requests in our app: the Fetch API and the Axios library.

    So, why using a new library to retrieve data? let’s try answering this legit question in the next section.

    Comparison With Fetch And Axios

    We already have many ways to make HTTP requests in our React Apps, and two of the most popular is the Fetch API and the Axios library. They are both great and allows us to fetch or send data easily. However, once the operation is done, they will not help us to cache or paginate data, you have to do it on our own.

    Axios or Fetch will just handle the request and return the expected response, nothing more.

    And compared to SWR, it’s a bit different because the SWR under the hood uses the Fetch API to request data from the server — it’s kind of a layer built on top of it. However, it has some nice features such as caching, pagination, scroll position recovery, dependent fetching, etc, and to be precise a certain level of reactivity out of the box that Axios or Fetch do not have. It’s a big advantage because having such features help to make our React Apps fast and user-friendly and reduce markedly the size of our code.

    And to conclude, just keep in mind that SWR is not the same as Axios or Fetch even if it helps to deal with HTTP requests. SWR is more advanced than them, it provides some enhancements to keep our app synchronized with the back-end and hence increases the performance of our app.

    Now we know what’s differences SWR has compared to the Axios library or the Fetch API, it’s time to dive into why using such a tool.

    Recommended reading: Consuming REST APIs In React With Fetch And Axios

    Why Using SWR For Data Fetching?

    As I said earlier SWR ships with some handy features that help to increase the usability of your app easily. With SWR, you can paginate your data in no-time using useSWRPages, you can also fetch data that depends on another request or recover a scroll position when you get back to a given page, and so much more.

    Usually, we show to the user a loading message or a spinner while fetching data from the server. And with SWR, you can make it better by showing to the user the cached or stale data while retrieving new data from the API. And once that operation is done, it will revalidate the data to show the new version. And you don’t need to do anything, SWR will cache the data the first time you fetch it and retrieve it automatically when a new request is made.

    So far, we already see why using SWR over Axios or Fetch is better depending obviously on what you are aiming to build. But for many cases, I will recommend using SWR because it has great features that go beyond just fetching and returning data.

    That said, we can now start building our React app and use the SWR library to fetch remote data.

    So, let’s start by setting up a new project.

    Setting Up

    As I said earlier in the introduction, we will build an app that fetches data from the Pokemon API. You can use a different API if you want too, I will stick with it for now.

    And to create a new app, we need to run the following command on the terminal:

    npx create-react-app react-swr

    Next, we need to install the SWR library by first navigating to the folder that holds the React app.

    cd react-swr

    And run on the terminal the following command to install the SWR package.

    yarn add swr

    Or if you’re using npm:

    npm install swr

    Now we have all set up done, let’s structure the project as follow to start using SWR:

    src
    ├── components
    |  └── Pokemon.js
    ├── App.js
    ├── App.test.js
    ├── index.js
    ├── serviceWorker.js
    ├── setupTests.js
    ├── package.json
    ├── README.md
    ├── yarn-error.log
    └── yarn.lock

    As you can see, the folder structure is simple. The only thing to notice is the components folder that holds the Pokemon.js file. It will be used later as a presentational component to show a single Pokemon once we get data from the API.

    Great! With that in place, we can now start fetching data from the API using useSWR.

    Fetching Remote Data

    The SWR package has some handy features as we have seen above. However, there are two ways of configuring this library: either locally or globally.

    A local setup means that every time we create a new file, we have to setup SWR again to be able to fetch remote data. And a global setup allows us to reuse a part of our configuration within different files because a fetcher function can be declared once and used everywhere.

    And no worries, we will see both in this article, but for now, let’s get hands dirty and add some meaningful code in the App.js file.

    Displaying The Data

    import React from 'react'
    import useSWR from 'swr'
    import { Pokemon } from './components/Pokemon'
    
    const url = 'https://pokeapi.co/api/v2/pokemon'
    
    const fetcher = (...args) => fetch(...args).then((res) => res.json())
    
    function App() {
        const { data: result, error } = useSWR(url, fetcher)
    
        if (error) return <h1>Something went wrong!</h1>
        if (!result) return <h1>Loading...</h1>
    
        return (
            <main className='App'>
                <h1>Pokedex</h1>
                <div>
                    {result.results.map((pokemon) => (
                        <Pokemon key={pokemon.name} pokemon={pokemon} />
                    ))}
                </div>
            </main>
        )
    }
    export default App

    As you can see, we start by importing useSWR from the SWR library. This declares the URL of the API you want to get data from, and a function to fetch these data.

    The function fetcher is used here to transform the data into JSON. It receives the data fetched as an argument and returns something.

    Notice that here, I use the Rest operator ((...args)) since I’m not sure of the type and length of data received as a parameter, therefore, I copy everything before passing it again as an argument to the fetch method provided by useSWR which transforms the data into JSON and returns it.

    That said, the fetcher and the url of the API can be now passed as parameters to the useSWR hook. With that, it can now make the request and it returns two states: the data fetched and an error state. And data: result is the same as data.result, we use object destructuring to pull result from data.

    With the returned values, we can now check if the data is successfully fetched and then loop through it. And for each user, use the Pokemon component to display it.

    Now we have the data and pass it down to the Pokemon Component, it’s time to update Pokemon.js to be able to receive and display the data.

    Creating The Pokemon Component

    import React from 'react'
    import useSWR from 'swr'
    
    const fetcher = (...args) => fetch(...args).then((res) => res.json())
    
    export const Pokemon = ({ pokemon }) => {
        const { name } = pokemon
        const url = 'https://pokeapi.co/api/v2/pokemon/' + name
    
        const { data, error } = useSWR(url, fetcher)
    
        if (error) return <h1>Something went wrong!</h1>
        if (!data) return <h1>Loading...</h1>
    
        return (
            <div className='Card'>
                <span className='Card--id'>#{data.id}</span>
                <img
                    className='Card--image'
                    src={data.sprites.front_default}
                    alt={name}
                />
                <h1 className='Card--name'>{name}</h1>
                <span className='Card--details'>
                    {data.types.map((poke) => poke.type.name).join(', ')}
                </span>
            </div>
        )
    }

    Here, we have a component that receives a single Pokemon data from the API and displays it. However, the data received does not contain all fields needed, hence we have to make another request to the API to get the complete Pokemon object.

    And as you can see, we use the same process to retrieve the data even if this time we append the name of the Pokemon to the URL.

    By the way, if you are not familiar with destructuring, ({ pokemon }) is the same as receiving props and accessing to the pokemon object with props.pokemon. It’s just a shorthand to pull out values from objects or arrays.

    With that in place, if you navigate to the root folder of the project and run on the terminal the following command:

    yarn start

    Or if you’re using npm:

    npm start

    You should see that the data are successfully fetched from the Pokemon API and displayed as expected.

    fetching

    Fetching illustration. (Large preview)

    Great! We are now able to fetch remote data with SWR. However, this setup is a local one and can be a bit redundant because you can already see that App.js and Pokemon.js use the same fetcher function to do the same thing.

    But luckily, the package comes with a handy provider named SWRConfig that helps to configure SWR globally. It’s a wrapper component that allows child components to use the global configuration and therefore the fetcher function.

    To setup SWR globally, we need to update the index.js file because it’s where the App component is rendered using React DOM. If you want, you can use SWRConfig directly in the App.js file.

    Configuring SWR Globally

    import React from 'react'
    import ReactDOM from 'react-dom'
    import { SWRConfig } from 'swr'
    import App from './App'
    import './index.css'
    
    const fetcher = (...args) => fetch(...args).then((res) => res.json())
    
    ReactDOM.render(
        <React.StrictMode>
            <SWRConfig value={{ fetcher }}>
                <App />
            </SWRConfig>
        </React.StrictMode>,
        document.getElementById('root')
    )

    As you can see, we start by importing SWRConfig which is a provider that needs to wrap the higher component or just part of your React app that needs to use SWR features. It takes as props a value that expects an object of config. You can pass more than one property to the config object, here I just need the function to fetch data.

    Now, instead of declaring the fetcher function in every file, we create it here and pass it as value to SWRConfig. With that, we can now retrieve data at any level in our app without creating another function and hence avoid redundancy.

    Besides that, fetcher is equal to fetcher: fetcher, it’s just syntactic sugar proposed by ES6. With that change, we need now to update our components to use the global config.

    Using The Global SWR Config

    import React from 'react'
    import useSWR from 'swr'
    import { Pokemon } from './components/Pokemon'
    
    const url = 'https://pokeapi.co/api/v2/pokemon'
    
    function App() {
        const { data: result, error } = useSWR(url)
    
        if (error) return <h1>Something went wrong!</h1>
        if (!result) return <h1>Loading...</h1>
    
        return (
            <main className='App'>
                <h1>Pokedex</h1>
                <div>
                    {result.results.map((pokemon) => (
                        <Pokemon key={pokemon.name} pokemon={pokemon} />
                    ))}
                </div>
            </main>
        )
    }
    export default App

    Now we only need to pass the url to useSWR, instead of passing the url and fetcher method. Let’s also tweak the Pokemon component a bit.

    import React from 'react'
    import useSWR from 'swr'
    
    export const Pokemon = ({ pokemon }) => {
        const { name } = pokemon
        const url = 'https://pokeapi.co/api/v2/pokemon/' + name
    
        const { data, error } = useSWR(url)
    
        if (error) return <h1>Something went wrong!</h1>
        if (!data) return <h1>Loading...</h1>
    
        return (
            <div className='Card'>
                <span className='Card--id'>#{data.id}</span>
                <img
                    className='Card--image'
                    src={data.sprites.front_default}
                    alt={name}
                />
                <h1 className='Card--name'>{name}</h1>
                <span className='Card--details'>
                    {data.types.map((poke) => poke.type.name).join(', ')}
                </span>
            </div>
        )
    }

    You can already see that we have no fetcher function anymore, thanks to the global configuration which passes the function to useSWR under the hood.

    Now, you can use the global fetcher function everywhere in your app. The only thing that the useSWR hook needs to fetch remote data is the URL.

    However, we can still enhance the setup furthermore by creating a custom hook to avoid declaring the URL again and again, and instead, just pass as parameter the path.

    Advanced Setup By Creating A Custom Hook

    To do so, you have to create a new file in the root of the project named useRequest.js (you can name it whatever you want) and add this code block below to it.

    import useSwr from 'swr'
    
    const baseUrl = 'https://pokeapi.co/api/v2'
    
    export const useRequest = (path, name) => {
        if (!path) {
            throw new Error('Path is required')
        }
    
        const url = name ? baseUrl + path + '/' + name : baseUrl + path
        const { data, error } = useSwr(url)
    
        return { data, error }
    }

    Here, we have a function that receives a path and optionally a name and appends it to the base URL to build the complete URL. Next, it checks if a name parameter is received or not and handle it consequently.

    Then, that URL is passed as a parameter to the useSWR hook to be able to fetch the remote data and return it. And if no path is passed, it throws an error.

    Great! we need now to tweak the components a bit to use our custom hook.

    import React from 'react'
    import { useRequest } from './useRequest'
    import './styles.css'
    import { Pokemon } from './components/Pokemon'
    
    function App() {
        const { data: result, error } = useRequest('/pokemon')
    
        if (error) return <h1>Something went wrong!</h1>
        if (!result) return <h1>Loading...</h1>
    
        return (
            <main className='App'>
                <h1>Pokedex</h1>
                <div>
                    {result.results.map((pokemon) => (
                        <Pokemon key={pokemon.name} pokemon={pokemon} />
                    ))}
                </div>
            </main>
        )
    }
    export default App

    Now, instead of using the SWR hook, we use the custom hook built on top of it and then pass as expected the path as an argument. With that in place, everything will work like before but with a much cleaner and flexible configuration.

    Let’s also update the Pokemon component.

    import React from 'react'
    import { useRequest } from '../useRequest'
    
    export const Pokemon = ({ pokemon }) => {
        const { name } = pokemon
        const { data, error } = useRequest('/pokemon', name)
    
        if (error) return <h1>Something went wrong!</h1>
        if (!data) return <h1>Loading...</h1>
    
        return (
            <div className='Card'>
                <span className='Card--id'>#{data.id}</span>
                <img
                    className='Card--image'
                    src={data.sprites.front_default}
                    alt={name}
                />
                <h1 className='Card--name'>{name}</h1>
                <span className='Card--details'>
                    {data.types.map((poke) => poke.type.name).join(', ')}
                </span>
            </div>
        )
    }

    You can already see how our custom hook makes things easier and more flexible. Here, we just need to pass additionally the name of the Pokemon to fetch to useRequest and it handles everything for us.

    I hope you start enjoying this cool library — However, we still have things to discover because SWR offers so many features, and one of them is useSWRPages which is a hook to paginate data easily. So, let’s use that hook in the project.

    Paginate Our Data With useSWRPages

    SWR allows us to paginate data easily and request only a part of it, and when needed refetch data to show for the next page.

    Now, let’s create a new file in the root of the project usePagination.js and use it as a custom hook for pagination.

    import React from 'react'
    import useSWR, { useSWRPages } from 'swr'
    import { Pokemon } from './components/Pokemon'
    
    export const usePagination = (path) => {
        const { pages, isLoadingMore, loadMore, isReachingEnd } = useSWRPages(
            'pokemon-page',
            ({ offset, withSWR }) => {
                const url = offset || `https://pokeapi.co/api/v2${path}`
                const { data: result, error } = withSWR(useSWR(url))
    
                if (error) return <h1>Something went wrong!</h1>
                if (!result) return <h1>Loading...</h1>
    
                return result.results.map((pokemon) => (
                    <Pokemon key={pokemon.name} pokemon={pokemon} />
                ))
            },
            (SWR) => SWR.data.next,
            []
        )
    
        return { pages, isLoadingMore, loadMore, isReachingEnd }
    }

    As you can see, here we start by importing useSWRPages which is the helper that allows paginating data easily. It receives 4 arguments: the key of the request pokemon-page which is also used for caching, a function to fetch the data that returns a component if the data are successfully retrieved, and another function that takes the SWR object and request data from the next page, and an array of dependencies.

    And once the data fetched, the function useSWRPages returns several values, but here we need 4 of them: the pages that is the component returned with the data, the function isLoadingMore which checks if the data are currently fetched, the function loadMore that helps fetching more data, and the method isReachingEnd which determines whether there is still data to retrieve or not.

    Now we have the custom hook that returns the needed values to paginate data, we can now move to the App.js file and tweak it a bit.

    import React from 'react'
    import { usePagination } from './usePagination'
    import './styles.css'
    
    export default function App() {
        const { pages, isLoadingMore, loadMore, isReachingEnd } = usePagination(
            '/pokemon'
        )
    
        return (
            <main className='App'>
                <h1>Pokedex</h1>
                <div>{pages}</div>
                <button
                    onClick={loadMore}
                    disabled={isLoadingMore || isReachingEnd}
                >
                    Load more...
                </button>
            </main>
        )
    }

    Once the usePagination hook imported, we can now pass the path as a parameter and get back the returned values. And since pages is a component, we don’t need to loop through the data or anything like that.

    Next, we use the function loadMore on the button to fetch more data and disable it if the retrieving operation is not finished or if there is no data to fetch.

    Great! with that change, we can now browse on the root of the project and start the server with this command to preview our app.

    yarn start

    Or if you’re using npm:

    npm start

    You should see that the data are successfully fetched and if you click on the button, new data will be retrieved by SWR.

    Pagination. (Large preview)

    So far, we have seen in practice the SWR library, and I hope you are finding value on it. However, it still has some features to offer. Let’s dive into these functionalities in the next section.

    Other Features Of SWR

    The SWR library has a bunch of handy things that simplifies the way we build React apps.

    Focus Revalidation

    It’s a feature that allows updating or revalidating to be precise the data when you re-focus a page or switch between tabs. And by default, this functionality is enabled, but you can disable it anyway if it does not fit your need. It can be useful especially if you have data with high-level-frequency updates.

    Refetch on Interval

    The SWR library allows refetching data after a certain amount of time. It can be handy when your data changes at high speed or you need to make a new request to get a piece of new information from your database.

    Local Mutation

    With SWR, you can set a temporary local state that will update automatically when new data are fetched(revalidation). This feature comes in play particularly when you deal with an Offline-first approach, it helps to update data easily.

    Scroll Position Recovery

    This feature is very handy, especially when it comes to dealing with huge lists. It allows you to recover the scroll position after getting back to the page. And in any case, it increases the usability of your app.

    Dependent Fetching

    SWR allows you to fetch data that depends on other data. That means it can fetch data A, and once that operation is done, it uses it to fetch data B while avoiding waterfalls. And this feature helps when you have relational data.

    That said, SWR helps to increase the user experience in any matter. It has more features than that, and for many cases it’s better to use it over the Fetch API or the Axios library.

    Conclusion

    Throughout this article, we have seen why SWR is an awesome library. It allows remote data fetching using React Hooks and helps to simplify some advanced features out of the box such as pagination, caching data, refetching on interval, scroll position recovery, and so on. SWR is also backend agnostic which means it can fetch data from any kind of APIs or databases. In definitive, SWR increases a lot the user experience of your React apps, it has a bright future and you should keep an eye on it or better use it in your next React app.

    You can preview the finished project live here.

    Thanks for reading!

    Next Steps

    You can go on to check the following links which will give you a better understanding beyond the scope of this tutorial.

    • SWR
    • SWR Docs

    Further Reading on SmashingMag:

    • Styling Components In React
    • Better Reducers With Immer
    • Higher-Order Components In React
    • Building Reusable React Components Using Tailwind

    (ks, ra, yk, il)

    From our sponsors: An Introduction To SWR: React Hooks For Remote Data Fetching

    Posted on 22nd June 2020Web Design
    FacebookshareTwittertweetGoogle+share

    Related posts

    Archived
    22nd March 2023
    Archived
    18th March 2023
    Archived
    20th January 2023
    Thumbnail for 25788
    Handling Continuous Integration And Delivery With GitHub Actions
    19th October 2020
    Thumbnail for 25778
    A Monthly Update With New Guides And Community Resources
    19th October 2020
    Thumbnail for 25781
    Supercharge Testing React Applications With Wallaby.js
    19th October 2020
    Latest News
    • Archived
      22nd March 2023
    • Archived
      18th March 2023
    • Archived
      20th January 2023
    • 20201019 ML Brief
      19th October 2020
    • Thumbnail for 25788
      Handling Continuous Integration And Delivery With GitHub Actions
      19th October 2020
    • Thumbnail for 25786
      The Future of CX with Larry Ellison
      19th October 2020
    News Categories
    • Digital Marketing
    • Web Design

    Our services

    Website Design
    Website Design

    A website is an important part of any business. Professional website development is an essential element of a successful online business.

    We provide website design services for every type of website imaginable. We supply brochure websites, E-commerce websites, bespoke website design, custom website development and a range of website applications. We love developing websites, come and talk to us about your project and we will tailor make a solution to match your requirements.

    You can contact us by phone, email or send us a request through our online form and we can give you a call back.

    More Information

    Digital Marketing
    Digital Marketing

    Our digital marketeers have years of experience in developing and excuting digital marketing strategies. We can help you promote your business online with the most effective methods to achieve the greatest return for your marketing budget. We offer a full service with includes the following:

    1. Social Media Marketing

    2. Email & Newsletter Advertising

    3. PPC - Pay Per Click

    4. A range of other methods are available

    More Information

    SEO
    SEO Services

    SEO is an essential part of owning an online property. The higher up the search engines that your website appears, the more visitors you will have and therefore the greater the potential for more business and increased profits.

    We offer a range of SEO services and packages. Our packages are very popular due to the expanse of on-page and off-page SEO services that they cover. Contact us to discuss your website and the SEO services that would best suit to increase your websites ranking.

    More Information

    E-commerce
    E-commerce Websites

    E-commerce is a rapidly growing area with sales online increasing year on year. A professional E-commerce store online is essential to increase sales and is a reflection of your business to potential customers. We provide professional E-commerce websites custom built to meet our clients requirements.

    Starting to sell online can be a daunting task and we are here to make that journey as smooth as possible. When you work with Cunningham Web Solutions on your E-commerce website, you will benefit from the experience of our team and every detail from the website design to stock management is carefully planned and designed with you in mind.

    More Information

    Social Media Services
    Social Media Services

    Social Media is becoming an increasingly effective method of marketing online. The opportunities that social media marketing can offer are endless and when managed correctly can bring great benefits to every business.

    Social Media Marketing is a low cost form of advertising that continues to bring a very good ROI for our clients. In conjuction with excellent website development and SEO, social media marketing should be an essential part of every digital marketing strategy.

    We offer Social Media Management packages and we also offer Social Media Training to individuals and to companies. Contact us to find out more.

    More Information

    Cunningham Web Solutions
    © Copyright 2025 | Cunningham Web Solutions
    • Home
    • Our Services
    • FAQ's
    • Account Services
    • Privacy Policy
    • Contact Us