SWR v1 is here: What’s new?

Introduction: What’s SWR?

SWR is a hooks library that provides React Hooks for remote data fetching. As the SWR docs state, the name “SWR” is derived from stale-while-revalidate, which is an HTTP cache invalidation strategy.

In a nutshell, the stale-while-revalidate strategy simply means serving or returning the stale (cached) data while you revalidate (fetch) the updated data and serve the updated data to the UI once it is returned. The revalidation of stale data occurs under the hood on user focus or network reconnect.

The result of this is that our application components get a stream of fresh data constantly, making our UI blazing fast, very reactive, and more responsive.

Another awesome feature we get out of the box that redounds to our application performance is deduplication. Deduplication is a technique to eliminate redundant data, and by implementing this technique, SWR does intelligent fetching.

What this is means is that when we render a component that reuses the useSWR hook multiple times, SWR would prevent multiple uses of the useSWR hook to revalidate data if the keys are the same, consequently eliminating unnecessary network requests because only one request would be made and stale data would be served to subsequent requests.

In this article, we’ll be looking at the awesome additions to SWR version 1, but if you are new to SWR, you can get started by reading our previous useSWR article.

New features in SWR v1

1. Smaller size and improved performance

SWR version 1 provides a significantly smaller library and improved performance features like tree shaking. According to the documentation, version 1 is significantly smaller — 41% smaller core or 24% smaller when gzipped.

The SWR package is tree-shakable because performance is one of the most important features of SWR.

Version 1 supports path imports as seen below:

import useSWR from 'swr'
import useSWRInfinite from 'swr/infinite'

With path imports, in cases where we are not using the useSWRInfinite hook, it would not be bundled in our application. Removing dead code makes our final bundle size significantly smaller.

By making the library more tree-shakable and lightweight, our application will have a smaller bundle, a leaner runtime, and a smaller node_modules directory.

2. Custom cache provider

By default, SWR uses a global cache. However, version 1 takes this further by providing the provider API. The provider API consists of a cache provider that is a map-like object that matches the following TypeScript definition:

interface Cache<Data> {
  get(key: string): Data | undefined
  set(key: string, value: Data): void
  delete(key: string): void
}

The cache provider is passed to the provider option of the SWRConfig as seen below:

import useSWR, { SWRConfig } from 'swr'

function App() {
  return (
    <SWRConfig value={{ provider: () => new Map() }}>
      <Blog/>
    </SWRConfig>
  )
}

The result of this is that our custom cache provider will be used by all the SWR hooks within SWRConfig. In other words, all the SWR hooks inside Blog will read and write from that map instance, but the SWR hooks that are not nested within the cache provider fall back to the default cache, which is an empty map. Because of this, cache providers should be placed higher in the component tree or outside render.

Cache providers are intended to adapt SWR to support more storage options, and they can be a JavaScript Map instance or other cache provider implementation depending on our use case.

SWR version 1 provides experimental support for extending the current cache provider. Consequently, we can sync the cache provider with the local storage, reset the cache between test cases, and more with the extended cache provider.

Also, in version 1 we can get access to the current cache provider when inside a React component by using the useSWRConfig hook as seen below:

import { useSWRConfig } from 'swr'

const Post() {
  const { cache, ...extraConfig } = useSWRConfig()
  cache.get(key) // Get the current data for the specified key.
  cache.clear()  // Clear all the cache. SWR will revalidate upon re-render.
  // ...
}

N.B., writing to the cache directly might cause undefined behaviors of SWR. The recommended practice is to use SWR APIs such as mutation.

3. useSWRConfig()

While the SWRConfig context provides global configuration options for all SWR hooks, the new useSWRConfig() hook enables us to access these options when inside a React component.

Consider the code below:

import { useSWRConfig } from 'swr'

function MyComponent () {
  const { refreshInterval, mutate, ...restConfig } = useSWRConfig()
  // ... do something
}

From our example on caching, we saw that we can also access the cache using useSWRConfig.

4. Immutable mode

Out of the box, SWR supports automatic revalidation on the following events:

Revalidate on focus

This revalidation occurs when we refocus a page or switch between tabs. This helps to provide fresh data to our app. By default, this feature is turned on, but you can disable it via the revalidateOnFocus option.

Revalidate on interval

In many cases, our app’s data can become stale quickly because of many devices, multiple users, and multiple open tabs. This feature enables SWR to perform polling on interval, and this provides a way to synchronize to the latest state and update the data on the UI over time.

You can enable this by setting the refreshInterval option with the value in the fetcher function:

useSWR('/api/todos', fetcher, { refreshInterval: 2000 })

The above code simply means polling would only occur every 2000 milliseconds.

Also, SWR enables us to perform polling when the window is invisible — if refreshInterval is enabled — by using the refreshWhenHidden option, and when the browser is offline using the refreshWhenOffline option.

Revalidate on reconnect

This revalidation occurs when networks recover, e.g., in a scenario when the user is back online. It can be configured using the revalidateOnReconnect option.

In version 1, SWR provides a helper, the useSWRImmutable hook, to make state immutable. This means the state does not change when we revalidate.

The useSWRImmutable hook is similar to the useSWR hook and we can make state immutable using both as seen below:

import useSWR from 'swr'
import useSWRImmutable from 'swr/immutable'

useSWRImmutable(key, fetcher, options) // makes resourse immutable 

useSWR(key, fetcher, {
  revalidateIfStale: false,
  revalidateOnFocus: false,
  revalidateOnReconnect: false
})

// equivalent to
useSWRImmutable(key, fetcher) // makes resourse immutable 

In the code above, the two hooks make the data immutable once it is cached. useSWRImmutable does it automatically for us.

5. Middleware

The SWR middleware API provides a great way to abstract and reuse logic.

The middleware is a closure that receives the SWR hook as an argument and wraps around the useSWR hook, thereby enabling us to execute logic before and after invoking the useSWR hooks.

Consider the code below:

function SWRMiddleware (useSWRNext) {
  return (key, fetcher, config) => {
    // beform operations before invoking useSWR()

    // Handle the next middleware, or invokes `useSWR` hook if this is the last middleware.
    const swr = useSWRNext(key, fetcher, config)

    // befrom operations after invoking useSWR()
    return swr
  }
}

The SWR middleware is very useful and powerful, and a lot of ideas can be implemented using this feature. An example from the documentation is a request logger.

The logger middleware is a function decorator that decorates the fetcher function with the ability to log requests — the SWR key in this case:

function logger(useSWRNext) {
  return (key, fetcher, config) => {
    // Add logger to the original fetcher.
    const extendedFetcher = (...args) => {
      console.log('SWR Request:', key)
      return fetcher(...args)
    }

    // Execute the hook with the new fetcher.
    return useSWRNext(key, extendedFetcher, config)
  }
}

Consequently, when we use this middleware, the SWR key is logged to the console:

...
// ... used from inside your component
useSWR(key, fetcher, { use: [logger] })
SWR Request: /api/user1
SWR Request: /api/user2
...

To use this feature, we pass an array of middlewares to either SWRConfig or useSWR:

<SWRConfig value={{ use: [middlewareA, middleWareB, middlewareC] }}>

// or...

useSWR(key, fetcher, { use: [middlewareA, middleWareB, middlewareC] })

When dealing with multiple middlewares, each middleware is nested within the other and the last middleware receives the SWR hook.

6. Fallback data

This new feature simply enables us to provide arbitrary prefetched data for all SWR with specific keys:

<SWRConfig value={{
  fallback: {
    '/user': { name: 'Eagles', ... },
    '/posts': ...,
    '/pages': ...,
    ...
  }
}}>
  <App/>
</SWRConfig>

These prefetched data can be displayed as placeholder content on your page while your application revalidates. This improves the user experience and it is very helpful in scenarios such as Static Generation (SSG) and Server-side Rendering (SSR).

Also, for consistency’s sake and to avoid confusion, the old initialData has been renamed to fallbackData but it still provides a single fallback value for the specified SWR hook.

Conclusion

SWR is an awesome, well-thought-out, lightweight, and fast data-fetching library. It is transport and protocol agnostic — it supports both REST and GraphQL, it supports suspense, and it is TypeScript ready. The patterns implemented in SWR make developers’ lives easier.

And SWR version 1 is definitely a must-use for every developer. You can learn more about version 1 here. You can also read the changelog for more information.

The post SWR v1 is here: What’s new? appeared first on LogRocket Blog.

This article was republished from its original source.
Call Us: 1(800)730-2416

Pixeldust is a 20-year-old web development agency specializing in Drupal and WordPress and working with clients all over the country. With our best in class capabilities, we work with small businesses and fortune 500 companies alike. Give us a call at 1(800)730-2416 and let’s talk about your project.

FREE Drupal SEO Audit

Test your site below to see which issues need to be fixed. We will fix them and optimize your Drupal site 100% for Google and Bing. (Allow 30-60 seconds to gather data.)

Powered by

SWR v1 is here: What’s new?

On-Site Drupal SEO Master Setup

We make sure your site is 100% optimized (and stays that way) for the best SEO results.

With Pixeldust On-site (or On-page) SEO we make changes to your site’s structure and performance to make it easier for search engines to see and understand your site’s content. Search engines use algorithms to rank sites by degrees of relevance. Our on-site optimization ensures your site is configured to provide information in a way that meets Google and Bing standards for optimal indexing.

This service includes:

  • Pathauto install and configuration for SEO-friendly URLs.
  • Meta Tags install and configuration with dynamic tokens for meta titles and descriptions for all content types.
  • Install and fix all issues on the SEO checklist module.
  • Install and configure XML sitemap module and submit sitemaps.
  • Install and configure Google Analytics Module.
  • Install and configure Yoast.
  • Install and configure the Advanced Aggregation module to improve performance by minifying and merging CSS and JS.
  • Install and configure Schema.org Metatag.
  • Configure robots.txt.
  • Google Search Console setup snd configuration.
  • Find & Fix H1 tags.
  • Find and fix duplicate/missing meta descriptions.
  • Find and fix duplicate title tags.
  • Improve title, meta tags, and site descriptions.
  • Optimize images for better search engine optimization. Automate where possible.
  • Find and fix the missing alt and title tag for all images. Automate where possible.
  • The project takes 1 week to complete.