swr

React Hooks for Data Fetching

MIT License

Downloads
9.7M
Stars
29.3K
Committers
182

Bot releases are visible (Hide)

swr - v2.1.0

Published by huozhi over 1 year ago

Feature

Checkout subscription docs and useSWRInfinite parallel fetching docs for more details

Patches

Misc

New Contributors

Full Changelog: https://github.com/vercel/swr/compare/v2.0.4...v2.1.0

swr - v2.0.4

Published by huozhi over 1 year ago

Patches

Misc

New Contributors

Full Changelog: https://github.com/vercel/swr/compare/v2.0.3...v2.0.4

swr - v2.0.3

Published by huozhi over 1 year ago

Patches

Chores

New Contributors

Full Changelog: https://github.com/vercel/swr/compare/v2.0.2...v2.0.3

swr - v2.0.2

Published by huozhi over 1 year ago

swr - v2.0.1

Published by shuding almost 2 years ago

In this patch release, we majorly improved typing support and SWR can infer the types based on the configuration.

  • When the suspense option is true, the returned data will exclude undefined and the isLoading will always be false.
  • When the fallbackData option is provided, the returned data will be the same type of fallbackData, and the isLoading will always be false.

Here's a demo for it:

https://user-images.githubusercontent.com/4800338/213288879-ffbeeeb5-aca5-4a65-8229-69fbf9b0bf70.mp4

What's Changed

New Contributors

Full Changelog: https://github.com/vercel/swr/compare/2.0.0...v2.0.1

swr - 2.0.0

Published by shuding almost 2 years ago

Announcing SWR 2.0

We are excited to announce the release of SWR 2.0! The new version comes with a lot of improvements:

  • New useSWRMutation hook
  • Enhanced mutation and optimistic UI capabilities
  • SWR DevTools
  • Preload resource
  • Improved React 18 support

And more!

Read our blog post and migration guide: https://swr.vercel.app/blog/swr-v2

What's Changed

New Contributors

Full Changelog: https://github.com/vercel/swr/compare/1.2.2...2.0.0

swr - 2.0.0-rc.3

Published by shuding almost 2 years ago

What's Changed

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

swr - 2.0.0-rc.1

Published by shuding almost 2 years ago

The last RC before SWR 2.0. This release includes several small fixes with one breaking change.

Breaking

In this release, we are dropping IE 11 support, and using ES2018 as the build target. However, when using SWR in a framework or using a bundler (esbuild, Webpack, etc.), you can still target ES5 or using a browserlist configuration to customize this.

The benefit of this change is, we can now use faster native APIs to make SWR more performant, instead of using old alternatives. A benchmark shows a 4.7x speed improvement of the useSWR() function call during SSR, when we change Object.assign({}, a, b) to { ...a, ...b }.

Details can be found in #2249.

What's Changed

New Contributors

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

swr - 2.0.0-rc.0

Published by shuding about 2 years ago

The SWR 2.0 release candidate. This RC has one breaking change, a new option for mutation APIs, and some bug fixes & improvements.

Highlights & Breakings

A failed mutation will not cause useSWR's error to be updated:

const { error, mutate } = useSWR('/api/user', getUser)

return <button onClick={async () => {
  try {
    await mutate(updateUser)
  } catch (mutationError) {
    // `mutationError` will not cause `error` to be updated.
  }
}}>Update User</button>

In 2.0, with the example above, error will only be coming from getUser and will be shared across all useSWR('/api/user') hooks. And mutation errors (mutationError) will be coming from mutations like updateUser calls, they will be separated from fetcher errors.

There is also a new option throwOnError for useSWRMutation to disable the default throwing behavior of trigger:

const { trigger } = useSWRMutation('/api/user', updateUser)

try {
  await trigger()
} catch (err) {
  // ... it throws when failed to trigger the mutation so you can
  // easily change the flow here
}
const { trigger, error } = useSWRMutation('/api/user', updateUser, {
  throwOnError: false
})

// You don't need to try-catch here, you can instead handle errors
// on the component level in a declarative way
await trigger()

Read more about this change in #2182.

What's Changed

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

swr - 2.0.0-beta.7

Published by shuding about 2 years ago

Most changes in this release are maintenance related, as we are finalizing everything for the upcoming 2.0 stable version.

What's Changed

New Contributors

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

swr - 2.0.0-beta.6

Published by shuding over 2 years ago

What's Changed

New Contributors

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

swr - 2.0.0-beta.5

Published by shuding over 2 years ago

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

swr - 2.0.0-beta.4

Published by shuding over 2 years ago

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

swr - 2.0.0-beta.3

Published by shuding over 2 years ago

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

swr - 2.0.0-beta.1

Published by shuding over 2 years ago

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

swr - 2.0.0-beta.0

Published by shuding over 2 years ago

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: https://github.com/vercel/swr/discussions/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: https://github.com/vercel/swr/compare/1.2.2...2.0.0-beta.0

swr - 1.3.0

Published by shuding over 2 years ago

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: https://github.com/vercel/swr/compare/1.2.2...1.3.0

swr - 1.2.2

Published by shuding over 2 years ago

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

Full Changelog: https://github.com/vercel/swr/compare/1.2.1...1.2.2

swr - 1.2.1

Published by shuding over 2 years ago

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

New Contributors

Full Changelog: https://github.com/vercel/swr/compare/1.2.0...1.2.1

swr - 1.2.0

Published by shuding over 2 years ago

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.

https://user-images.githubusercontent.com/3676859/151381238-f3aba769-91b6-4bfc-9285-df1b9ef51773.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: https://github.com/vercel/swr/compare/1.1.2...1.2.0