Skip to content
Docs
Change Log

Change Log

Please visit the SWR release page for all history releases.

2.0.0-beta.6

Published on Mon Jul 04 2022.

What's Changed

New Contributors

Full Changelog: https://github.com/vercel/swr/compare/2.0.0-beta.5...2.0.0-beta.6

2.0.0-beta.5

Published on Sun Jun 26 2022.

Highlights & Breakings

Mutate Multiple Keys (#1946, #1989)

You can now pass a filter function to the global mutate API to match any keys and mutate them together:

import { mutate } from 'swr'
// Or from the hook if you customized the cache provider:
// { mutate } = useSWRConfig()

mutate(
  key => typeof key === 'string' && key.startsWith('/api/item?id='),
  data => update(data),
  true
)

This action will match all keys starting with '/api/item?id=', and replace their data with update, then re-fetch after the mutation. The signature is the same as the current mutate API:

mutate(
  '/api/item?id=123',
  data => update(data),
  true
)

The only difference is if you pass a function instead of a specific key, SWR will use it to match and mutate all the data in the cache. It will be convenient to use this to batch updates, or mutate keys by pattern.

Worth noting that it works with any key types, too:

useSWR(['item', 123], ...)
useSWR(['item', 124], ...)
useSWR(['item', 125], ...)

mutate(
  key => Array.isArray(key) && key[0] === 'item',
  undefined,
  false
)

The mutation above will match all 3 keys and set the values to undefined (clear them), and skip the revalidation at the end. So another technique is to clear everything with this (e.g. when logging out):

mutate(
  () => true,
  undefined,
  false
)

More use cases and discussions can be found in the original RFC: #1946.

What's Changed

Full Changelog: https://github.com/vercel/swr/compare/2.0.0-beta.4...2.0.0-beta.5

2.0.0-beta.4

Published on Sat Jun 18 2022.

Highlights

Preload API (#2026)

SWR now has a preload API that you can call programmatically to kick off the request early. For example, you can do preload('/api/user', fetcher) even outside of React:

import { useState } from 'react'
import useSWR, { preload } from 'swr'

const fetcher = (url) => fetch(url).then((res) => res.json())

// Preload the resource before rendering the User component below,
// this prevents potential waterfalls in your application.
// You can also start preloading when hovering the button or link, too.
preload('/api/user', fetcher)

function User() {
  const { data } = useSWR('/api/user', fetcher)
  ...
}

export default function App() {
  const [show, setShow] = useState(false)
  return (
    <div>
      <button onClick={() => setShow(true)}>Show User</button>
      {show ? <User /> : null}
    </div>
  )
}

So at the moment of clicking the button and actually rendering the User component, the resource is likely loaded already. If the request depends on some props or states, you can also preload it when hovering the button:

function App({ userId }) {
  const [show, setShow] = useState(false)
  return (
    <div>
      <button
        onClick={() => setShow(true)}
        onHover={() => preload('/api/user?id=' + userId, fetcher)}
      >
        Show User
      </button>
      {show ? <User /> : null}
    </div>
  )
}

Demo: https://codesandbox.io/s/swr-preloading-14bikv?file=/src/App.js

Function as SWRConfig value (#2024)

A new way to extend the SWR global configuration:

<SWRConfig value={{ revalidateOnFocus: false, dedupingInterval: 5000 }}>
  <div>
    <Header/>
    <SWRConfig value={config => ({ ...config, dedupingInterval: 1000 })}>
      <Main />
    </SWRConfig>
  </div>
</SWRConfig>

Where you can inherit the parent configuration and override the dedupingInterval value, but reuse the other options.

Breakings

SWRConfig.defaultSWRConfig.defaultValue (#2023)

This is a currently undocumented API, but planned to go stable with the 2.0 release. You can access to SWR’s default options via the SWRConfig.defaultValue static and read-only property.

What's Changed

New Contributors

Full Changelog: https://github.com/vercel/swr/compare/2.0.0-beta.3...2.0.0-beta.4

2.0.0-beta.3

Published on Sun May 15 2022.

Highlights

Better React 18 Support (#1962)

This is a change of SWR's internal implementation detail. For developers that use SWR, it will just work out of the box without any changes in their apps.

Brought to you by @promer94 and @shuding, this release includes a core refactoring that improves React 18 support by adopting APIs like useSyncExternalStore and startTransition internally. Especially when rendering UIs concurrently with React 18, this new SWR version ensures stronger UI consistency.

Worth note that the current stable 1.x version of SWR still works well in React 18.

This core change isn't breaking and does not affect React <=17 apps.

Breakings

Avoid using Suspense on the server-side (#1931)

When using suspense: true with SWR on the server-side (including pre-rendering in Next.js), it's now required to provide the initial data via fallbackData or fallback. This means that you can't use Suspense to fetch data on the server side as of today, but either doing fully client-side data fetching, or fetch the data via the framework (such as getStaticProps in Next.js).

While Suspense for libraries is still experimental, this behavior might change before the 2.0 stable release. More discussions can be found here: #1906.

What's Changed

New Contributors

Full Changelog: https://github.com/vercel/swr/compare/2.0.0-beta.1...2.0.0-beta.3

2.0.0-beta.1

Published on Sun Apr 17 2022.

SWR 2.0 on its way! Check https://github.com/vercel/swr/releases/tag/2.0.0-beta.0 for the previous 2.0 beta updates.

💖 Give feedback in discussion: https://github.com/vercel/swr/discussions/1932.

Highlights

New isLoading state (#1928)

Previously, useSWR only returns a isValidating state, which is an indicator of both initial requests and automatic & manual revalidations. It includes polling requests and focus revalidations, etc.

But if you need to display an initial skeleton while loading the data, you will have to do something like

const isLoading = typeof data === 'undefined' && !error

...which is a popular pattern in the community. In this case, isValidating doesn't help much.

In this release, useSWR, useSWRInfinite and useSWRImmutable will return an extra isLoading state along with the isValidating state. They will fit to different scenarios:

function Stock() {
  const { data, isLoading, isValidating } = useSWR(STOCK_API, fetcher, {
    refreshInterval: 3000
  });

  // If it's still loading the initial data, there is nothing to display.
  // We return a skeleton here.
  if (isLoading) return <div className="skeleton" />;

  // Otherwise, display the data and a spinner that indicates a background
  // revalidation.
  return (
    <>
      <div>AAPL ${data}</div>
      {isValidating ? <div className="spinner" /> : null}
    </>
  );
}

In the example above, we display a skeleton while loading the data. After the data is loaded, we show a spinner next to the data whenever we are re-fetching (revalidating):

CleanShot 2022-04-17 at 02 40 22

You can find the full code for this example here: https://codesandbox.io/s/swr-isloading-v8dfpy.

New keepPreviousData option (#1929)

When doing data fetching based on continuous user actions, e.g. real-time search when typing, keeping the previous fetched data can improve the UX a lot.

In SWR 2.0, there is now a keepPreviousData option to enable that behavior. Here's a simple search UI:

function Search() {
  const [search, setSearch] = React.useState('');

  const { data, isLoading } = useSWR(`/search?q=${search}`, fetcher, {
    keepPreviousData: true
  });

  return (
    <div>
      <input
        type="text"
        value={search}
        onChange={(e) => setSearch(e.target.value)}
        placeholder="Search..."
      />

      <div className={isLoading ? "loading" : ""}>
        {data?.products.map(item => <Product key={item.id} name={item.name} />)
      </div>
    </div>
  );
}

With keepPreviousData enabled, you will still get the previous data even if you change the SWR key and the data for the new key starts loading again. This improves the visual continuity quite a lot, the search feels smoother after flipping the switch:

https://user-images.githubusercontent.com/3676859/163695903-a3eb1259-180e-41e0-821e-21c320201194.mp4

You can find the full code for this example here: https://codesandbox.io/s/swr-keeppreviousdata-fsjz3m.

Breakings

Type InfiniteFetcher is renamed to SWRInfiniteFetcher (#1930)

This type was already marked as deprecated in 1.x, and it now removed in this beta. If you are using it, please do the following change:

- import { InfiniteFetcher } from 'swr/infinite'
+ import { SWRInfiniteFetcher } from 'swr/infinite'

What's Changed

Full Changelog: https://github.com/vercel/swr/compare/2.0.0-beta.0...2.0.0-beta.1

Last updated on August 27, 2021