Skip to content

Releases: vercel/swr

2.0.0-beta.0

11 Apr 23:55
2564501
Compare
Choose a tag to compare
2.0.0-beta.0 Pre-release
Pre-release

SWR 2.0 coming soon, and this is the first beta version!

Keep in mind that APIs might still change until the stable release. Documentation will also be updated once stable.

💖 Give feedback in discussion: #1919.

Highlights

useSWRMutation — dedicated API for remote mutations, e.g. POST (#1450)

Added in #1450, the new useSWRMutation hook covers all the use cases of:

  • Requests that change data on the remote side: such as POST, PUT, DELETE, etc.
  • Requests that need to be triggered manually, instead of automatically by SWR.
  • Passing extra argument to fetcher, when triggering a request.
  • Knowing the status of a mutation, similar to isValidating but for mutations.
  • A lot more...

Here's a quick example of how it looks:

import useSWRMutation from 'swr/mutation'

async function sendRequest(url, { arg }) {
  return fetch(url, {
    method: 'POST',
    body: JSON.stringify(arg)
  })
}

function App() {
  const { trigger } = useSWRMutation('/api/user', sendRequest)

  return <button onClick={() => {
    trigger({ username: 'johndoe' })
  }}>Create User</button>
}

In this example, the "fetcher", which is sendRequest, will receive the value { username: 'johndoe' } as the arg from the second parameter. The request will only be triggered when clicking the button.

The new useSWRMutation hook is actually more powerful than this, it also supports:

  • Optimistic updates
  • Automatic error rollback
  • Detect and avoid race conditions between useSWR
  • Populate the cache of useSWR after mutation finishes
  • ...

More examples to come.

Breakings

Fetcher no longer accepts multiple arguments (#1864)

Previously, if the key is an array, the values will be passed to the fetcher function as arguments separately. In 2.0, the key will always be passed to the fetcher as is.

Before:

// SWR 1.x
useSWR([1, 2, 3], (a, b, c) => {
  assert(a === 1)
  assert(b === 2)
  assert(c === 3)
})

After 2.0.0:

// SWR 2.0.0
useSWR([1, 2, 3], (a) => {
  assert(a === [1, 2, 3])
})

Internal structure of the cached data (#1863)

This change affects the code that directly reads/writes to the cache, or provides a cache preset. For example if you have something like cache.set(key, value), you'll have to update your code.

Previously, the cached value of key will be the associated data, so this was guaranteed:

// SWR 1.x
assert(cache.get(key) === data)

And we keep other states (error, isValidating) with a special, prefixed key. Something like '$err$' + key.

Since 2.0.0, the internal structure will be an object that holds all the current states:

// SWR 2.0.0
assert(cache.get(key) === { data, error, isValidating })

So you will have to do the following change to your code, get:

- cache.get(key)
+ cache.get(key)?.data

And set:

- cache.set(key, data)
+ cache.set(key, { ...cache.get(key), data })

What's Changed

New Contributors

Full Changelog: 1.2.2...2.0.0-beta.0

1.3.0

10 Apr 23:49
9b9771e
Compare
Choose a tag to compare

What's Changed

  • type: fix type error on SWRConfig by @himself65 in #1913
  • chore: update React 18 dependencies by @shuding in #1824
  • test: fix an act warning by @koba04 in #1888
  • feat: support functional optimisticData by @huozhi in #1861
  • bugfix: make suspense and revalidateIfStale work together by @simowe in #1851

Full Changelog: 1.2.2...1.3.0

1.2.2

18 Feb 19:11
f24c621
Compare
Choose a tag to compare

Highlights of This Release

populateCache Option Now Supports Function

We added better Optimistic UI support in v1.2.0. However, what if your API is only returning a subset of the data (such as the mutated part), that can be populated into the cache? Usually, an extra revalidation after that mutation is needed. But now you can also use a function as populateCache to transform the mutate result into the full data:

await mutate(addTodo(newTodo), {
  optimisticData: [...data, newTodo],
  rollbackOnError: true,
  populateCache: (addedTodo, currentData) => {
    // `addedTodo` is what the API returns. It's not
    // returning a list of all current todos but only
    // the new added one.
    // In this case, we can transform the mutate result
    // together with current data, into the new data
    // that can be updated.
    return [...currentData, addedTodo];
  },
  // Since the API already gives us the updated information,
  // we don't need to revalidate here.
  revalidate: false,
});

The new definition:

populateCache?: boolean | ((mutationResult: any, currentData: Data) => Data)

Here is a demo for it: https://codesandbox.io/s/swr-basic-forked-hi9svh

Bug Fixes

What's Changed

  • refactor: revalidateIfStale has an effect on updates, not only mounting by @koba04 in #1837
  • fix: reset stale unmountedRef in suspense by @promer94 in #1843
  • test: add a test for the behavior of revalidateOnMount when the key has been changed by @koba04 in #1847
  • feat: Support populateCache as a function by @shuding in #1818

Full Changelog: 1.2.1...1.2.2

1.2.1

02 Feb 18:45
c63cafc
Compare
Choose a tag to compare

Highlights of This Release

shouldRetryOnError accepts a function

Previously shouldRetryOnError is either true or false. Now it accepts a function that conditionally determines if SWR should retry. Here's a simple example:

const fetcher = url => fetch(url).then(res => {
  // Fetcher throws if the response code is not 2xx.
  if (!res.ok) throw res
  return res.json()
})

useSWR(key, fetcher, {
  shouldRetryOnError: (error) => {
    // We skip retrying if the API is returning 404:
    if (error.status === 404) return false
    return true
  }
})

Thanks to @sairajchouhan for contributing!

What's Changed

  • shouldRetryOnError accepts a function that can be used to conditionally stop retrying by @sairajchouhan in #1816
  • build(deps-dev): bump next from 12.0.8 to 12.0.9 by @dependabot in #1821
  • fix: useSWRInfinite revalidates with revalidateOnMount by @koba04 in #1830

New Contributors

Full Changelog: 1.2.0...1.2.1

1.2.0

26 Jan 17:26
bfb9edc
Compare
Choose a tag to compare

Highlights of This Release

Optimistic Updates with Auto Error Rollback

There are now some new options in mutate:

mutate(patchUser(user), {
  optimisticData: user,
  populateCache: true,
  rollbackOnError: true,
  revalidate: true,
})

Here the cache will be immediately updated to user, the “optimistic value”. And then a request (remote mutation) is started via patchUser(user) and the response will be written to the cache. If that request fails, the original result will be rolled back safely so the optimistic value will be gone. And after all those finish, a revalidation will start to fetch the latest value.

This is extremely helpful for building the optimistic UI pattern.

You can do the same for the global mutate, just remember to pass the key. Also, the current mutate APIs stay unchanged so mutate(data, false) works the same.

Here's an example: https://codesandbox.io/s/swr-basic-forked-k5hps.

CleanShot.2022-01-27.at.15.39.58.mp4

.mjs Support

SWR now has .mjs exported for bundlers that prefer this format.

This doesn’t break environments that don’t support .mjs. An alternative .esm.js and CJS bundle are also published.

You can read more about ES modules here.

What's Changed

New Contributors

Full Changelog: 1.1.2...1.2.0

1.2.0-beta.1

12 Jan 17:12
d45b05d
Compare
Choose a tag to compare
1.2.0-beta.1 Pre-release
Pre-release

What's Changed

New Contributors

Full Changelog: 1.1.2...1.2.0-beta.1

1.2.0-beta.0

28 Dec 22:52
d1a76c9
Compare
Choose a tag to compare
1.2.0-beta.0 Pre-release
Pre-release

Highlights of This Release

Dedicated API for Optimistic Updates with Auto Rollback on Error

There are now some new options in mutate:

mutate(patchUser(user), {
  optimisticData: user,
  populateCache: true,
  rollbackOnError: true,
  revalidate: true,
})

Here the cache will be immediately updated to user, the “optimistic value”. And then a request (remote mutation) is started via patchUser(user) and the response will be written to the cache. If that request fails, the original result will be rolled back safely so the optimistic value will be gone. And after all those finish, a revalidation will start to fetch the latest value.

This is extremely helpful for building the optimistic UI pattern.

You can do the same for the global mutate, just remember to pass the key. Also, the current mutate APIs stay unchanged so mutate(data, false) works the same.

Here's an example: https://codesandbox.io/s/swr-basic-forked-k5hps.

What's Changed

Full Changelog: 1.1.2...1.2.0-beta.0

1.1.2

26 Dec 20:32
49ee4e9
Compare
Choose a tag to compare

Highlights of This Release

Use the Latest Fetcher Function

SWR will now use the latest fetcher function passed to the hook, when sending the request. Previously it uses the initial snapshotted fetcher.

Avoid Unnecessary Auto Revalidations

When refocusing on the window with state changes (like clicking a button that changes the SWR key immediately), SWR now avoids revalidations if they're not necessary. Details can be found in #1720.

New Types for useSWRInfinite

Two types for useSWRInfinite are added: SWRInfinteHook and SWRInfinteKeyLoader. You can use them to type the hook and the getKey function.

New populateCache option for mutate

A new option to control if the mutation data should be written to the cache. You can find the details in #1729.

What's Changed

  • Make polyfill for requestAnimationFrame more robust by @thomaspaulmann in #1707
  • type(infinite): export SWRInfinteHook and SWRInfiniteKeyLoader from infinite, rename InfiniteFetcher to SWRInfiniteFetcher by @houkanshan in #1714
  • feat: Ensure auto revalidations are executed after state updates by @shuding in #1720
  • Add moduleNameMapper to jest by @shuding in #1724
  • Improve test by @promer94 in #1725
  • feat: Use the latest reference of fetcher by @shuding in #1727
  • fix: Re-export InfiniteFetcher by @shuding in #1728
  • feat: Add populateCache option to mutate by @shuding in #1729
  • Fix local state sharing example deps by @huozhi in #1737
  • Merge states for concurrent requests by @shuding in #1741
  • Skip error retrying when document is not active and improve tests by @shuding in #1742

New Contributors

Full Changelog: 1.1.1...1.1.2

1.1.2-beta.1

23 Dec 19:33
68dfcc1
Compare
Choose a tag to compare
1.1.2-beta.1 Pre-release
Pre-release

Highlights of This Release

1. More Tests and Better Code Coverage

We now have 23 test suits of 202 total test cases, with a 98.06% test coverage. The core files and main functionalities are now 100% covered. Kudos to @promer94 for improving it!

2. Use the Latest Fetcher Function

SWR will now use the latest fetcher function passed to the hook, when sending the request. Previously it uses the initial snapshotted fetcher.

3. Avoid Unnecessary Auto Revalidations

When refocusing on the window with state changes (like clicking a button that changes the SWR key immediately), SWR now avoids revalidations if they're not necessary. Details can be found in #1720.

4. New Types for useSWRInfinite

Two types for useSWRInfinite are added: SWRInfinteHook and SWRInfinteKeyLoader. You can use them to type the hook and the getKey function.

What's Changed

New Contributors

Full Changelog: 1.1.2-beta.0...1.1.2-beta.1

1.1.2-beta.0

15 Dec 15:44
fd3a649
Compare
Choose a tag to compare
1.1.2-beta.0 Pre-release
Pre-release

What's Changed

New Contributors

Full Changelog: 1.1.1...1.1.2-beta.0