https://swr.vercel.app/blog/swr-v2
Skip to content
SWR
DocsExamplesBlog
[ ]
/
GitHub
[ ]
/
* Announcing SWR 2.0
* Announcing SWR 1.0
* Docs
+ Getting Started
+ API
+ Global Configuration
+ Data Fetching
+ Auto Revalidation
+ Arguments
+ Mutation & Revalidation
+ Error Handling
+ Conditional Data Fetching
+ Pagination
+ Prefetching
+ Next.js SSG and SSR
+ TypeScript
+ Suspense
+ Middleware
+ Advanced
o Understanding SWR
o Cache
o Performance
o React Native
o Developer Tools
+ Change Log
* Examples
+ Basic Usage
+ Authentication
+ Optimistic UI
+ Infinite Loading
+ Error Handling
+ Next.js SSR
* Blog
+ Announcing SWR 2.0
o #Mutation and Optimistic UI
o #SWR DevTools
o #Preloading Data
o #isLoading
o #Preserving Previous State
o #Extending Configurations
o #Improved React 18 Support
o #Migration Guide
o #Changelog
o #The Future & Thank You!
+ Announcing SWR 1.0
English
light
On This Page
* Mutation and Optimistic UI
* useSWRMutation
* Optimistic UI
* Mutate Multiple Keys
* SWR DevTools
* Preloading Data
* isLoading
* Preserving Previous State
* Extending Configurations
* Improved React 18 Support
* Migration Guide
* Fetcher No Longer Accepts Multiple Arguments
* Global Mutate No Longer Accepts a getKey Function
* New Required Property keys() for Cache Interface
* Changed Cache Internal Structure
* SWRConfig.default Is Renamed as SWRConfig.defaultValue
* Type InfiniteFetcher Is Renamed as SWRInfiniteFetcher
* Avoid Suspense on Server
* ES2018 as the Build Target
* Changelog
* The Future & Thank You!
Question? Give us feedback -Edit this page on GitHub -
Blog
Announcing SWR 2.0
Announcing SWR 2.0
December 9th, 2022 by Shu DingJiachi LiuToru KobayashiYixuan Xu
Today, we are excited to announce the release of SWR 2.0! This new
version comes with a lot of improvements and new features: new
mutation APIs and improvements to optimistic UI scenarios, new
DevTools, better support for concurrent rendering, etc. We would like
to give a big shout-out to all the contributors and maintainers who
helped make this release possible.
Mutation and Optimistic UI#
useSWRMutation#
Mutation is an important part of the data-fetching process. They
allow you to make changes to your data both locally and remotely. Our
existing mutate API allows you to revalidate and mutate resources
manually. In SWR 2.0, the new hook useSWRMutation makes it even
simpler to remotely change data using a declarative API. You can set
up a mutation using the hook, and then activate it later:
import useSWRMutation from 'swr/mutation'
async function sendRequest(url, { arg }) {
return fetch(url, {
method: 'POST',
body: JSON.stringify(arg)
})
}
function App() {
const { trigger, isMutating } = useSWRMutation('/api/user', sendRequest)
return (
)
}
The example above defines a sendRequest mutation that affects the '/
api/user' resource. Unlike useSWR, useSWRMutation will not
immediately start the request upon rendering. Instead, it returns a
trigger function that can later be called to manually start the
mutation.
The sendRequest function will be called when the button is clicked,
with the extra argument { username: 'johndoe' }. The value of
isMutating will be set to true until the mutation has finished.
Additionally, this new hook addresses other issues you may have with
mutations:
* Optimistically update the UI while data is being mutated
* Automatically revert when mutation fails
* Avoid any potential race conditions between useSWR and other
mutations of the same resource
* Populate the useSWR cache after mutation completes
* ...
You can find in-depth API references and examples by reading the docs
or scrolling through the next few sections.
Optimistic UI#
Optimistic UI is an excellent model for creating websites that feel
fast and responsive; however, it can be difficult to implement
correctly. SWR 2.0 has added some new powerful options to make it
easier.
Let's say we have an API that adds a new todo to the todo list and
sends it to the server:
await addNewTodo('New Item')
In our UI, we use a useSWR hook to display the todo list, with an
"Add New Item" button that triggers this request and asks SWR to
re-fetch the data via mutate():
const { mutate, data } = useSWR('/api/todos')
return <>
{/* Display data */}
>
However, the await addNewTodo(...) request could be very slow. When
it's ongoing, users still see the old list even if we can already
know what the new list will look like. With the new optimisticData
option, we can show the new list optimistically, before the server
responds:
const { mutate, data } = useSWR('/api/todos')
return <>
{/* Display data */}
>
SWR will immediately update the data with the optimisticData value,
and then send the request to the server. Once the request finishes,
SWR will revalidate the resource to ensure it's the latest.
Like many APIs, if the addNewTodo(...) request returns us the latest
data from the server, we can directly show that result, too (instead
of starting a new revalidation)! There's the new populateCache option
to tell SWR to update the local data with the mutate response:
const { mutate, data } = useSWR('/api/todos')
return <>
{/* Display data */}
>
At the same time, we don't need another revalidation afterward as the
response data is from the source of truth, we can disable it with the
revalidate option:
const { mutate, data } = useSWR('/api/todos')
return <>
{/* Display data */}
>
Lastly, if addNewTodo(...) fails with an exception, we can revert the
optimistic data ([...data, 'New Item']) we just set, by setting
rollbackOnError to true (which is also the default option). When that
happens, SWR will roll back data to the previous value.
const { mutate, data } = useSWR('/api/todos')
return <>
{/* Display data */}
>
All these APIs are supported in the new useSWRMutation hook as well.
To learn more about them, you can check out our docs. And here is a
demo showing that behavior:
Optimistic UI with automatic error rollback
Mutate Multiple Keys#
The global mutate API now accepts a filter function, where you can
mutate or revalidate specific keys. This will be helpful for use
cases such as invalidating all the cached data. To learn more, you
can read Mutate Multiple Keys in the docs.
import { mutate } from 'swr'
// Or from the hook if you have customized your cache provider:
// { mutate } = useSWRConfig()
// Mutate single resource
mutate(key)
// Mutate multiple resources and clear the cache (set to undefined)
mutate(
key => typeof key === 'string' && key.startsWith('/api/item?id='),
undefined,
{ revalidate: false }
)
SWR DevTools#
SWRDevTools is a browser extension that helps you debug your SWR
cache and the fetch results. Check our devtools section for how to
use devtools in your application.
[cache-view]
Preloading Data#
Preloading data can improve the user experience tremendously. If you
know the resource is going to be used later in the application, you
can use the new preload API to start fetching it early:
import useSWR, { preload } from 'swr'
const fetcher = (url) => fetch(url).then((res) => res.json())
// You can call the preload function in anywhere
preload('/api/user', fetcher)
function Profile() {
// The component that actually uses the data:
const { data, error } = useSWR('/api/user', fetcher)
// ...
}
export function Page () {
return
}
In this example, the preload API is called in the global scope. This
means that we start to preload the resource before React even starts
to render anything. And when the Profile component is being rendered,
the data can probably be available already. If it's still ongoing,
the useSWR hook will reuse that ongoing preloading request instead of
starting a new one.
The preload API can also be used in cases like preloading data for
another page that will likely be rendered. More information about
prefetching data with SWR can be found here.
isLoading#
isLoading is a new state returned by useSWR, that indicates if the
request is still ongoing, and there is no data loaded yet.
Previously, the isValidating state represents both the initial
loading state and revalidating state so we had to check if both data
and error are undefined to determine if it was the initial loading
state.
Now, it is so easy that you can directly use the isLoading value to
render a loading message:
import useSWR from 'swr'
function Profile() {
const { data, isLoading } = useSWR('/api/user', fetcher)
if (isLoading) return
loading...
return
hello {data.name}!
}
Note that isValidating is still present so you can still use it to
show a loading indicator for revalidations.
We have added the new Understanding SWR page to describe how SWR
returns values, which includes the difference between isValidating
and isLoading, and how to combine them to improve user experience.
Preserving Previous State#
The keepPreviousData option is a new addition that allows you to keep
the data that was fetched before. This improves UX immensely when
you're fetching data based on user actions happening in real time,
like with a live search feature, where the resource's key keeps
changing:
function Search() {
const [search, setSearch] = React.useState('');
const { data, isLoading } = useSWR(`/search?q=${search}`, fetcher, {
keepPreviousData: true
})
return (
);
}
Keep previous search results when keepPreviousData has been enabled
Check the code on CodeSandbox and you can read more about it here.
Extending Configurations#
SWRConfig can now accept a function value. When you have multiple
levels of , the inner receives the parent configuration
and returns a new one. This change makes it more flexible to
configure SWR in a large codebase. More information can be found here
.
({
dedupingInterval: parentConfig.dedupingInterval * 5,
refreshInterval: 100,
})}
>
Improved React 18 Support#
SWR has updated its internal code to use useSyncExternalStore and
startTransition APIs in React 18. These ensure stronger consistency
when rendering UI concurrently. This change doesn't require any user
code changes and all developers will benefit from it directly. Shims
are included for React 17 and below.
SWR 2.0 and all the new features are still compatible with React 16
and 17.
Migration Guide#
Fetcher No Longer Accepts Multiple Arguments#
key is now passed as a single argument.
- useSWR([1, 2, 3], (a, b, c) => {
+ useSWR([1, 2, 3], ([a, b, c]) => {
assert(a === 1)
assert(b === 2)
assert(c === 3)
})
Global Mutate No Longer Accepts a getKey Function#
Now, if you pass a function to the global mutate, it will be used as
a filter. Previously, you can pass a function that returns a key to
the global mutate:
- mutate(() => '/api/item') // a function to return a key
+ mutate('/api/item') // to mutate the key, directly pass it
New Required Property keys() for Cache Interface#
When you use your own cache implementation, the Cache interface now
requires a keys() method that returns all keys in the cache object,
similar to the JavaScript Map instances.
interface Cache {
get(key: string): Data | undefined
set(key: string, value: Data): void
delete(key: string): void
+ keys(): IterableIterator
}
Changed Cache Internal Structure#
The internal structure of the cache data will be an object that holds
all the current states.
- assert(cache.get(key) === data)
+ assert(cache.get(key) === { data, error, isValidating })
// getter
- cache.get(key)
+ cache.get(key)?.data
// setter
- cache.set(key, data)
+ cache.set(key, { ...cache.get(key), data })
You should not write to the cache directly, it might cause undefined
behavior.
SWRConfig.default Is Renamed as SWRConfig.defaultValue#
SWRConfig.defaultValue is the property for accessing the default SWR
config.
- SWRConfig.default
+ SWRConfig.defaultValue
Type InfiniteFetcher Is Renamed as SWRInfiniteFetcher#
- import type { InfiniteFetcher } from 'swr/infinite'
+ import type { SWRInfiniteFetcher } from 'swr/infinite'
Avoid Suspense on Server#
If you want to use suspense: true with SWR on the server-side,
including pre-rendering in Next.js, then you must provide initial
data via fallbackData or fallback. Today, this means that you can't
use Suspense to fetch data on the server side. Your other two options
are doing fully client-side data-fetching or getting your framework
to fetch the data for you (like getStaticProps does in Next.js).
ES2018 as the Build Target#
If you want to support IE 11, you have to target ES5 in your
framework or a bundler. This change has made a performance
improvement on SSR, and keeps the bundle size small.
Changelog#
Read the full Changelog on GitHub.
The Future & Thank You!#
With the new release of Next.js 13, we see a lot of exciting new
things as well as paradigm shifts in the React ecosystem: React
Server Components, streaming SSR, async components, and the use hook.
Many of them are related to data-fetching, and some of them have
overlapping use cases with SWR.
However, the goal of the SWR project remains the same. We want it to
be a drop-in library that is lightweight, framework agnostic, and a
little bit opinionated (i.e. revalidate upon focus). Instead of
trying to be a standard solution, we want to focus on innovations
that make the UX better. In the meantime, we are also doing research
on how to improve SWR with these new abilities of React.
We want to thank every one of the 143 contributors (+ 106 docs
contributors), as well as those who helps us out or gave feedback. A
special thanks goes to Toru Kobayashi for all his work on DevTools
and docs- we couldn't have done it without you!
Last updated on December 9, 2022
Announcing SWR 1.0
English
light
Powered by