React Hooks library for remote data fetching

Overview

SWR


Introduction

swr.vercel.app

SWR is a React Hooks library for remote data fetching.

The name “SWR” is derived from stale-while-revalidate, a cache invalidation strategy popularized by HTTP RFC 5861. SWR first returns the data from cache (stale), then sends the fetch request (revalidate), and finally comes with the up-to-date data again.

It features:

  • Transport and protocol agnostic data fetching
  • Fast page navigation
  • Revalidation on focus
  • Interval polling
  • Request deduplication
  • Local mutation
  • Pagination
  • TypeScript ready
  • SSR support
  • Suspense mode
  • React Native support
  • Minimal API

...and a lot more.

With SWR, components will get a stream of data updates constantly and automatically. Thus, the UI will be always fast and reactive.


Quick Start

import useSWR from 'swr'

function Profile() {
  const { data, error } = useSWR('/api/user', fetcher)

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}

In this example, the React Hook useSWR accepts a key and a fetcher function. The key is a unique identifier of the request, normally the URL of the API. And the fetcher accepts key as its parameter and returns the data asynchronously.

useSWR also returns 2 values: data and error. When the request (fetcher) is not yet finished, data will be undefined. And when we get a response, it sets data and error based on the result of fetcher and rerenders the component.

Note that fetcher can be any asynchronous function, so you can use your favourite data-fetching library to handle that part.

Check out swr.vercel.app for more demos of SWR, and Examples for the best practices.


Usage

Inside your React project directory, run the following:

yarn add swr

Or with npm:

npm install swr

API

const { data, error, isValidating, mutate } = useSWR(key, fetcher, options)

Parameters

  • key: a unique key string for the request (or a function / array / null) (advanced usage)
  • fetcher: (optional) a Promise returning function to fetch your data (details)
  • options: (optional) an object of options for this SWR hook

Return Values

  • data: data for the given key resolved by fetcher (or undefined if not loaded)
  • error: error thrown by fetcher (or undefined)
  • isValidating: if there's a request or revalidation loading
  • mutate(data?, shouldRevalidate?): function to mutate the cached data

Options

  • suspense = false: enable React Suspense mode (details)
  • fetcher = window.fetch: the default fetcher function
  • initialData: initial data to be returned (note: This is per-hook)
  • revalidateOnMount: enable or disable automatic revalidation when component is mounted (by default revalidation occurs on mount when initialData is not set, use this flag to force behavior)
  • revalidateOnFocus = true: auto revalidate when window gets focused
  • revalidateOnReconnect = true: automatically revalidate when the browser regains a network connection (via navigator.onLine)
  • refreshInterval = 0: polling interval (disabled by default)
  • refreshWhenHidden = false: polling when the window is invisible (if refreshInterval is enabled)
  • refreshWhenOffline = false: polling when the browser is offline (determined by navigator.onLine)
  • shouldRetryOnError = true: retry when fetcher has an error (details)
  • dedupingInterval = 2000: dedupe requests with the same key in this time span
  • focusThrottleInterval = 5000: only revalidate once during a time span
  • loadingTimeout = 3000: timeout to trigger the onLoadingSlow event
  • errorRetryInterval = 5000: error retry interval (details)
  • errorRetryCount: max error retry count (details)
  • onLoadingSlow(key, config): callback function when a request takes too long to load (see loadingTimeout)
  • onSuccess(data, key, config): callback function when a request finishes successfully
  • onError(err, key, config): callback function when a request returns an error
  • onErrorRetry(err, key, config, revalidate, revalidateOps): handler for error retry
  • compare(a, b): comparison function used to detect when returned data has changed, to avoid spurious rerenders. By default, dequal/lite is used.
  • isPaused(): function to detect whether pause revalidations, will ignore fetched data and errors when it returns true. Returns false by default.

When under a slow network (2G, <= 70Kbps), errorRetryInterval will be 10s, and loadingTimeout will be 5s by default.

You can also use a global configuration to provide default options.


Examples

Global Configuration

The context SWRConfig can provide global configurations (options) for all SWR hooks.

In this example, all SWRs will use the same fetcher provided to load JSON data, and refresh every 3 seconds by default:

import useSWR, { SWRConfig } from 'swr'

function Dashboard() {
  const { data: events } = useSWR('/api/events')
  const { data: projects } = useSWR('/api/projects')
  const { data: user } = useSWR('/api/user', { refreshInterval: 0 }) // don't refresh
  // ...
}

function App() {
  return (
    <SWRConfig
      value={{
        refreshInterval: 3000,
        fetcher: (...args) => fetch(...args).then(res => res.json())
      }}
    >
      <Dashboard />
    </SWRConfig>
  )
}

Data Fetching

fetcher is a function that accepts the key of SWR, and returns a value or a Promise. You can use any library to handle data fetching, for example:

import fetch from 'unfetch'

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

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

Or using GraphQL:

import { request } from 'graphql-request'

const fetcher = query => request('/api/graphql', query)

function App() {
  const { data, error } = useSWR(
    `{
      Movie(title: "Inception") {
        releaseDate
        actors {
          name
        }
      }
    }`,
    fetcher
  )
  // ...
}

If you want to pass variables to a GraphQL query, check out Multiple Arguments.

Note that fetcher can be omitted from the parameters if it's provided globally.

Conditional Fetching

Use null or pass a function as the key to useSWR to conditionally fetch data. If the functions throws an error or returns a falsy value, SWR will cancel the request.

// conditionally fetch
const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)

// ...or return a falsy value
const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)

// ... or throw an error when user.id is not defined
const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)

Dependent Fetching

SWR also allows you to fetch data that depends on other data. It ensures the maximum possible parallelism (avoiding waterfalls), as well as serial fetching when a piece of dynamic data is required for the next data fetch to happen.

function MyProjects() {
  const { data: user } = useSWR('/api/user')
  const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id)
  // When passing a function, SWR will use the return
  // value as `key`. If the function throws or returns
  // falsy, SWR will know that some dependencies are not
  // ready. In this case `user.id` throws when `user`
  // isn't loaded.

  if (!projects) return 'loading...'
  return 'You have ' + projects.length + ' projects'
}

Multiple Arguments

In some scenarios, it's useful to pass multiple arguments (can be any value or object) to the fetcher function. For example:

useSWR('/api/user', url => fetchWithToken(url, token))

This is incorrect. Because the identifier (also the index of the cache) of the data is '/api/user', so even if token changes, SWR will still have the same key and return the wrong data.

Instead, you can use an array as the key parameter, which contains multiple arguments of fetcher:

const { data: user } = useSWR(['/api/user', token], fetchWithToken)

// ...and pass it as an argument to another query
const { data: orders } = useSWR(user ? ['/api/orders', user] : null, fetchWithUser)

The key of the request is now the combination of both values. SWR shallowly compares the arguments on every render and triggers revalidation if any of them has changed. Keep in mind that you should not recreate objects when rendering, as they will be treated as different objects on every render:

// Don’t do this! Deps will be changed on every render.
useSWR(['/api/user', { id }], query)

// Instead, you should only pass “stable” values.
useSWR(['/api/user', id], (url, id) => query(url, { id }))

Dan Abramov explains dependencies very well in this blog post.

Manually Revalidate

You can broadcast a revalidation message globally to all SWRs with the same key by calling mutate(key).

This example shows how to automatically refetch the login info (e.g.: inside <Profile/>) when the user clicks the “Logout” button.

import useSWR, { mutate } from 'swr'

function App() {
  return (
    <div>
      <Profile />
      <button onClick={() => {
        // set the cookie as expired
        document.cookie = 'token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'

        // tell all SWRs with this key to revalidate
        mutate('/api/user')
      }}>
        Logout
      </button>
    </div>
  )
}

Mutation and Post Request

In many cases, applying local mutations to data is a good way to make changes feel faster — no need to wait for the remote source of data.

With mutate, you can update your local data programmatically, while revalidating and finally replace it with the latest data.

import useSWR, { mutate } from 'swr'

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

  return (
    <div>
      <h1>My name is {data.name}.</h1>
      <button onClick={async () => {
        const newName = data.name.toUpperCase()
        
        // update the local data immediately, but disable the revalidation
        mutate('/api/user', { ...data, name: newName }, false)
        
        // send a request to the API to update the source
        await requestUpdateUsername(newName)
        
        // trigger a revalidation (refetch) to make sure our local data is correct
        mutate('/api/user')
      }}>Uppercase my name!</button>
    </div>
  )
}

Clicking the button in the example above will send a POST request to modify the remote data, locally update the client data and try to fetch the latest one (revalidate).

But many POST APIs will just return the updated data directly, so we don’t need to revalidate again. Here’s an example showing the “local mutate - request - update” usage:

mutate('/api/user', newUser, false)      // use `false` to mutate without revalidation
mutate('/api/user', updateUser(newUser)) // `updateUser` is a Promise of the request,
                                         // which returns the updated document

Mutate Based on Current Data

In many cases, you are receiving a single value back from your API and want to update a list of them.

With mutate, you can pass an async function which will receive the current cached value, if any, and let you return an updated document.

mutate('/api/users', async users => {
  const user = await fetcher('/api/users/1')
  return [user, ...users.slice(1)]
})

Returned Data from Mutate

Most probably, you need some data to update the cache. The data is resolved or returned from the promise or async function you passed to mutate.

The function will return an updated document to let mutate update the corresponding cache value. It could throw an error somehow, every time when you call it.

try {
  const user = await mutate('/api/user', updateUser(newUser))
} catch (error) {
  // Handle an error while updating the user here
}

Bound mutate()

The SWR object returned by useSWR also contains a mutate() function that is pre-bound to the SWR's key.

It is functionally equivalent to the global mutate function but does not require the key parameter.

import useSWR from 'swr'

function Profile() {
  const { data, mutate } = useSWR('/api/user', fetcher)

  return (
    <div>
      <h1>My name is {data.name}.</h1>
      <button onClick={async () => {
        const newName = data.name.toUpperCase()
        // send a request to the API to update the data
        await requestUpdateUsername(newName)
        // update the local data immediately and revalidate (refetch)
        // NOTE: key is not required when using useSWR's mutate as it's pre-bound
        mutate({ ...data, name: newName })
      }}>Uppercase my name!</button>
    </div>
  )
}

SSR with Next.js

With the initialData option, you pass an initial value to the hook. It works perfectly with many SSR solutions such as getServerSideProps in Next.js:

export async function getServerSideProps() {
  const data = await fetcher('/api/data')
  return { props: { data } }
}

function App(props) {
  const initialData = props.data
  const { data } = useSWR('/api/data', fetcher, { initialData })

  return <div>{data}</div>
}

It is still a server-side rendered site, but it’s also fully powered by SWR in the client-side. Which means the data can be dynamic and update itself over time and user interactions.

Suspense Mode

You can enable the suspense option to use SWR with React Suspense:

import { Suspense } from 'react'
import useSWR from 'swr'

function Profile() {
  const { data } = useSWR('/api/user', fetcher, { suspense: true })
  return <div>hello, {data.name}</div>
}

function App() {
  return (
    <Suspense fallback={<div>loading...</div>}>
      <Profile/>
    </Suspense>
  )
}

In Suspense mode, data is always the fetch response (so you don't need to check if it's undefined). But if an error occurred, you need to use an error boundary to catch it.

Note that Suspense is not supported in SSR mode.

Error Retries

By default, SWR uses the exponential backoff algorithm to handle error retries. You can read more from the source code.

It's also possible to override the behavior:

useSWR(key, fetcher, {
  onErrorRetry: (error, key, option, revalidate, { retryCount }) => {
    if (retryCount >= 10) return
    if (error.status === 404) return

    // retry after 5 seconds
    setTimeout(() => revalidate({ retryCount: retryCount + 1 }), 5000)
  }
})

Prefetching Data

There’re many ways to prefetch the data for SWR. For top-level requests, rel="preload" is highly recommended:

<link rel="preload" href="/api/data" as="fetch" crossorigin="anonymous">

This will prefetch the data before the JavaScript starts downloading. And your incoming fetch requests will reuse the result (including SWR, of course).

Another choice is to prefetch the data conditionally. You can have a function to refetch and set the cache:

function prefetch() {
  mutate('/api/data', fetch('/api/data').then(res => res.json()))
  // the second parameter is a Promise
  // SWR will use the result when it resolves
}

And use it when you need to preload the resources (for example when hovering a link). Together with techniques like page prefetching in Next.js, you will be able to load both next page and data instantly.

Request Deduplication

SWR deduplicates requests by default. If you call the hook with the same key multiple times, only one request is made. Duplicated calls will receive a value from cache. Here, the 'api/user' key is used in two requests:

import useSWR from 'swr'

function UserProfileName() {
  const { data, error } = useSWR('/api/user', fetcher)

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
  return <p>Name: {data.name}!</p>
}

function UserProfileAvatar() {
  const { data, error } = useSWR('/api/user', fetcher)

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
  return <img src={data.avatarUrl} alt="Profile image" />
}

export default function App() {
  return (
    <div>
      <UserProfileName />
      <UserProfileAvatar />
    </div>
  )
}

By default, requests made within 2 seconds are deduped. This can be changed by setting the dedupingInterval option:

const { data, error } = useSWR('/api/user', fetcher, { dedupingInterval: 1000 })

This will deduplicate requests at an interval of 1 second.

Authors

Thanks to Ryan Chen for providing the awesome swr npm package name!


License

The MIT License.

Comments
  • New infinite loading API

    New infinite loading API

    This PR adds a new useSWRInfinite API for infinite loading, which is far more stable and easier to understand and use:

    const { data, error, mutate, size, setSize } = useSWRInfinite(getKey, fetcher?, options?)
    

    The new API signature is very similar to useSWR. One difference is that the first parameter getKey is a function that returns the key:

    (currentPageIndex, previousPageData) => keyOfThisPage
    

    API

    The returned object includes size and setSize, they are returned by an internal state inside the hook.

    • data: an array of paginated fetch response values.
    • mutate: same as useSWR's bound mutate function[1]
    • options: all current SWR options are supported, with 3 new options:
      • initialSize: number of pages should be loaded initially, default to 1
      • revalidateAll: always try to revalidate all pages[2], default to false
      • persistSize: don't reset the page size to 1 (or initialSize if set) when the first page's key changes #490

    [1]: note that the global mutate won't work with this new API [2]: useSWRInfinite supports all the revalidation options of SWR too (refreshInterval, revalidateOnFocus, revalidateOnReconnect...). However by default it will only revalidate the first page. You can change the behavior to revalidate all pages by setting revalidateAll to true.

    Why Renaming

    There're a lot of confusion about useSWRPages that people are using it for normal pagination use cases. However that's not necessary and you should implement it with page components or dynamic SWR keys.

    useSWRInfinite should only be used when you need dynamic number of fetch requests (a list that you can load more and append data to), and the key of each request depends on the previous data.

    Example 1: Paginated API

    GET /users?page=0&limit=10
    [
      { name: 'Alice' },
      { name: 'Bob' },
      { name: 'Cathy' },
      ...
    ]
    

    With useSWRInfinite:

    const { data } = useSWRInfinite(
      (index, previousPageData) => {
        // reached the end
        if (previousPageData && previousPageData.length === 0) return null
    
        // API key
        return `/users?page=${index}&limit=10`
      },
      fetcher, // same as useSWR
      opts     // same as useSWR
    )
    
    // render
    if (!data) return 'loading'
    return <>
      {data.map((users, index) => {
        // render each page
        return users.map(user => <div>{user.name}</div>)
      })}
    </>
    

    Example 2: Cursor Based Paginated API

    GET /users?cursor=123&limit=10
    {
      data: [
        { name: 'Alice' },
        { name: 'Bob' },
        { name: 'Cathy' },
        ...
      ],
      nextCursor: 456
    }
    

    With useSWRInfinite:

    const { data } = useSWRInfinite(
      (index, previousPageData) => {
        // reached the end
        if (previousPageData && previousPageData.data.length === 0) return null
    
        // first page, previousPageData is null
        if (index === 0) return `/users?limit=10`
    
        return `/users?cursor=${previousPageData.nextCursor}&limit=10`
      },
      fetcher, // same as useSWR
      opts.    // same as useSWR
    )
    

    Example 3: Advanced Features

    Here's an example showing how you can use this API to implement:

    • loadMore
    • isLoadingMore
    • isLoadingInitialData
    • isEmpty
    • isReachingEnd
    • change data source
    • refresh the entire list

    https://codesandbox.io/s/swr-infinite-z6r0r?file=/src/App.js

    Checklist

    • [x] cache page count
    • [x] scroll position restoration
    • [x] #391
    • [x] make setSize return promise
    • [x] update documentation (https://github.com/vercel/swr-site/pull/24)
    • [x] create examples (https://github.com/vercel/swr-site/pull/24)
    • [x] deprecate useSWRPages

    Latest release of this PR: [email protected].


    Related to #21, #70, #126, #133, #178, #189, #202, #205, #243, #246, #269, #289, #309, #311, #343, #347, #384, #396, #399, #434 (almost all our existing issues are about the undocumented pagination API 🙊).

    feature request discussion area: pagination RFC 
    opened by shuding 85
  • Data is not updated with `initialData`

    Data is not updated with `initialData`

    I'm on a Next.js app and here is my (simplified) code:

    const IndexPage = ({ data: initialData }) => {
      const [filters, setFilters] = useState(defaultFilters)
    
      const onChange = () => {
        ...
        setFilters(newFilters)
      }
    
      const query = getQuery(filters)
      const { data } = useSWR(`/api/resorts?${query}`, fetcher, { initialData })
    
      return (...)
    }
    
    Index.getInitialProps = async ctx => {
      const query = getQuery(defaultFilters)
      const data: Resort[] = await fetcher(`${getHost(ctx)}/api/resorts?${query}`)
      return { data }
    }
    

    I have an initial set of filter (defaultFilters) on which I query and pass to useSWR with initialData on first render. When the user changes one filter, the key should change as it's a new query, but useSWR still returns the old data, from the first call.

    When I remove initialData from useSWR it works but that's not what I want, I want to have SSR.

    Am I doing something wrong?

    area: cache 
    opened by Kerumen 57
  • Expose Cache

    Expose Cache

    This attempts to partially resolve #212 and resolves #161 and resolves #237 and resolves #158

    Implementation Notes

    I updated this to only expose the global cache, I kept the cache interface, adding a way to tell the set, delete and clear methods if you want to notify components reading from the cache, this way mutate can call cache.set and cache.set can also call mutate as a notification method without running on a infinite loop (mutate calls cache.set with this flag as false).

    I did this to come back to custom cache once I found a way to let mutate know which cache to call without manually passing it.

    ~I created a CacheInterface and make the global config create a default instance of the cache, also exported both the interface and the Cache class.~

    ~I also updated useSWR to read from the cache instance received through the context object.~

    ~I was not able, yet, to find a way to make mutate and trigger read from the correct cache instance, because they are global my only idea so far was to pass the cache instance as a third argument (probably optional), but that could make it hard to test components using a custom cache for tests and a default cache for the mutate call.~

    Missing things

    ~- useSWRPages is still using global cache (I haven't tried yet to use it here but I believe is the same as mutate and trigger)~ ~- mutate is still using global cache~ ~- trigger is still using global cache~

    Any feedback is welcomed!

    opened by sergiodxa 32
  • Possible to support object keys?

    Possible to support object keys?

    Would it be possible to support objects as keys rather than forcing everything to be a string?

    In my case I'm looking to do something like

    const { data } = useSwr(userDetail.prepare({ id: 5 }));
    

    which returns the same object given the same inputs. The object itself has a method on it that is called by the fetcher:

    function fetcher(preparedAction) {
        return preparedAction.call();
    }
    

    As it is this doesn't work because the object returned is forced to a string here: https://github.com/zeit/swr/blob/master/src/use-swr.ts#L66

    Given the cache is a Map using an object as a key works, eg. changing that line to the following appears to do what I want:

    else if (!key || typeof key !== 'object') {
            // convert null to ''
            key = String(key || '');
    }
    

    Wrapping it in an array does also work:

    const { data } = useSwr([userDetail.prepare({ id: 5 })]);
    

    but the ergonomics aren't as good (especially given if you forget to wrap it in an array it just doesn't work - no errors).

    Unfortunately other things assume it's a string as well - eg. CONCURRENT_PROMISES etc are just plain objects rather than a Map.

    Is this something that you would be willing to extend the API to accomodate?

    My alternative to make this work within the current API constraints would be to have prepare return a string that fetcher can look up into my own global cache... but I was thinking it would be nice to avoid this if swr already did that internally.

    feature request discussion 
    opened by davecoates 32
  • Keep previous result while revalidating

    Keep previous result while revalidating

    Is there an easy way, or if one could be added, to have useSWR keep the previous result while revalidating?

    My case is a search field, and after I've gotten my first data, I'd really like the returned data to stick until a new request has completed (or failed). Currently the data goes back to undefined whenever the key changes.

    feature request 
    opened by Svish 29
  • Is there a way to reset pages of `useSWRPages`?

    Is there a way to reset pages of `useSWRPages`?

    Hi

    I'm using swr for pagination in my local next.js project. My implementation is based on this example. The difference is that my component with useSWRPages is using dynamic route, which loads user's feed, and the route looks like this: /user/[username].

    The problem appears when I switch user feed with loaded pages. In more details:

    1. I, as a user, open user-A's feed, then load a number of pages (let's say 4).
    2. I change feed to user-B's.
    3. User-B's feed loads 4 pages, instead of 1.

    I'd tried to pass username in to useSWRPages's deps, and use it in key, but it didn't helped me. Is there any workarounds? Maybe I should pass something else in to the deps?

    There's is an issue that seems like similar to mine: #126.

    feature request area: pagination 
    opened by tem-tem 28
  • Have a way to clear cache

    Have a way to clear cache

    I'm writing tests for a component using useSWR, also with { suspense: true }, and if I render a component reading the same key (e.g. the same component with different keys) I'm getting the old cache in my second test.

    Not sure if this will be addressed with #158, but having a way to tell SWR to clear the cache of a certain key would be awesome for this use case.

    import { clearCache } from "swr";
    
    clearCache(); // clear all cache
    clearCache("/api/data"); // clear only a certain cache key
    

    ☝️ something like that.

    What I have tried:

    • mutate(key, null, false)
    • mutate(key, {}, false)

    Both doesn't work right since useSWR will still read that null or {} from the cache instead of triggering an immediate fetch and suspending the component.

    I will try to create a CodeSandbox to replicate this soon.

    feature request area: cache 
    opened by sergiodxa 28
  • Add subscription support to useSWR

    Add subscription support to useSWR

    This PR adds subscription support as proposed in https://github.com/vercel/swr/discussions/437#discussioncomment-25793

    The way it works uses the same API

    const { data } = useSWR("/api/messages", fetcher, {
      subscribe(key, mutate) {
        return subscribeToSomething(key, mutate);
      },
    });
    

    API

    Subscribe is a function receiving key and mutate.

    • key the unserialized key, what useSWR receives, it could be a string, array or function.
    • mutate is the same useSWR returns, already bound to the key

    The subscribe function must return an unsubscribe function, this unsubscribe function will be called in the case:

    1. The component using this useSWR unmount
    2. The subscribe fn is created again (it must be wrapped in useCallback to avoid this)
    3. The key changed

    A global subcribe function could be also used by setting it in SWRConfig.

    Examples

    WebSockets

    The most basic example is to use it go subscribe via WebSockets and get new data, e.g. in a chat application.

    const { data } = useSWR("/api/chat-messages", fetcher, {
      subscribe(key, mutate) {
        // start connection to the WebSocket API
        const ws = new WebSocket("wss://my.app/api/chat-messages");
        ws.onmessage = (event) => {
          mutate((messages) => [...messages, JSON.parse(event.data)], false);
        };
        return () => ws.close();
      },
    });
    

    Geolocation API

    We could use it to get new data from any type of stream, in this case Geolocation changes

    function fetcher() {
      return new Promise((resolve, reject) =>
        navigator.geolocation.getCurrentPosition(resolve, reject)
      );
    }
    
    const { data } = useSWR("geolocation", fetcher, {
      subscribe(_, mutate) {
        const id = navigator.geolocation.watchPosition((data) =>
          mutate(data, false)
        );
        return () => navigator.geolocation.clearWatch(id);
      },
    });
    

    Firebase (and other real-time databases)

    We could use it in combination with real-time databases like Firebase to get the current value in the fetcher and subscribe to updates for that same value.

    async function fetcher() {
      const ref = db.collection("cities").doc("SF");
      const doc = await ref.get();
      return doc.data();
    }
    
    function subscribe(_, mutate) {
      const ref = db.collection("cities").doc("SF");
      ref.on("value", (snapshot) => {
        mutate(snapshot.val(), false);
      });
      return ref.off;
    }
    
    const { data } = useSWR("db/cities/SF", fetcher, { subscribe });
    

    GraphQL

    We could use it with GraphQL to start a subscription in the same useSWR call.

    const { data } = useSWR(
      [gql`SOME GRAPHQL QUERY`, variables],
      (query, variables) => client.fetch(gql, { variables }),
      {
        subscribe([_, variables], mutate) {
          return client.subscribe(gql`SOME GRAPHQL SUBSCRIPTION QUERY`, {
            variables,
          });
        },
      }
    );
    

    LocalStorage

    It's also possible to use it to listen to global events like the storage one and get updates when another tab change the value in storage.

    const { data } = useSWR("storage-key", key => localStorage.get(key), {
      subscribe(key, mutate) {
        const listener = event => {
          if (event.key !== key) return;
          mutate(localStorage.get(key), false)
        });
        window.addEventListener("storage", listener);
        return () => window.removeEventListener("storage", listener);
      }
    });
    

    Checklist

    • [x] Add documentation
    • [x] Add examples to the folder
    opened by sergiodxa 27
  • Better support for react-native

    Better support for react-native

    Hi guys, it could be great to use AppState (https://reactnative.dev/docs/appstate) for revalidateOnFocus and NetInfo (https://github.com/react-native-community/react-native-netinfo) for revalidateOnReconnect, errorRetryInterval, loadingTimeout when running in react-native context.

    Any advice with that? im handling revalidations manually for this cases.

    Thanks !!!

    area: react-native 
    opened by outaTiME 27
  • Support multiple caching mechanisms

    Support multiple caching mechanisms

    Frontend based:

    • Memory (Map, the current cache mechanism)
    • Session Storage
    • Local Storage
    • WebSQL
    • IndexedDb

    Backend Based:

    • sqlite
    • LRUCache
    • Redis
    • Anything...?

    Suggestion

    My suggestion would be to allow providing a class that implements a new interface that supports a similar API to Map (get, set, delete?), defaulting to a MemoryCache that just uses Map

    Side Notes

    Frontend based caches could help add support for persistence. Backend based caches could help with adding support for SSR.

    This could also add the possibility for supporting TTLs if that's desired, potentially solving #4 Can also solve #7 by allowing users the track their own namespaces.

    As suggested by @netspencer, a layered cache architecture could be awesome too

    After reading #4 it looks like you might already be planning this, which is awesome!

    discussion area: cache 
    opened by aequasi 19
  • useSWR to fetch only one time

    useSWR to fetch only one time

    How can I use swr to fetch data only once? I don't need to refresh the data and revalidate. I prefer to use swr library for this and not just sending simple request and showing data, for couple of reasons:

    1. swr manages cache
    2. swr prevent a situation of update after unmount (no need to cancel request) and more great things swr has to offer..

    So how can I use swr for this? What I need to put in the options param?

    Is it a good idea to use it for this purpose? It feels like I'm using a sledgehammer to crack a nut.

    Thanks!

    opened by oran1248 18
  • `cache` not exported globally + `populateCache` not working as expected

    `cache` not exported globally + `populateCache` not working as expected

    Bug report

    Description / Observed Behavior

    Trying to import cache and use it outside of a component yields undefined cache?

    Expected Behavior

    Be able to access cache from anywhere in my application, including outside of components.

    Code Example

    import  { cache } from "swr"
    
    const tags = cache.get('/api/tags/list')
    

    (1) Additional Context

    My use case is when using "pure javascript" functions in my application, for instance when coding states using zustand i would like to access the global cache and get data from there so i can create optimistData outside of components and deal with my API / application.

    I believe this behaviour was possible on previous SWR version?

    (2) Additional Context

    By further investigating the docs i found out the mutate function is available globally ( but curiously cache isn't? ) and according to Update Cache After Mutation i should be able to achieve the same results by passing a function to populateCache.

    Repro Steps

    ....
    
    async function onSubmit(values, actions) {
      const { label } = values
    
      const addTag = post("/api/tags/add", { label })
    
      mutate("/api/tags/list", addTag, {
        populateCache: function (newTag, tags) {
          console.log("new tag ->", newTag)
          console.log("tags ->", tags)
          return [...tags, newTag]
        },
        revalidate: false,
      })
    
      actions.setSubmitting(false)
    }
    
    ....
    
    const ListTagsExample = () => {
      const { data: session } = useSession()
    
      const {
        data: tags,
        error: errorTags,
        isLoading: isLoadingTags,
      } = useSWR("/api/tags/list", fetcher)
    
      console.log('tags ->', tags)
    
      return <>{tags.length} fetched</>
    }
    

    Which does the trick, but for readability/convenience purposes i believe it would be much easier if i could simply do:

    
    import {cache} from 'swr'
    const cachedItems = cache.get('/items/list') || []
    
    try {
      const newItem = await fetchNewItem()
    }  catch(error){
     // ... do my error reporting
    }
    
    const optimistData = [...cachedItems, newItem]
    
    mutate('/api/items/list', optimisticData, { revalidate: true })
    
    

    OR, more importantly, if my application would have access to the global default cache object from SWR without the need to wrap the application on with SWRConfig and implement my own custom "singleton" provider?

    Final Thoughts

    Thanks a lot for all the hard work on the library, it's truly incredible and a huge time saver + loads of feature candy, i'm a big fan of your work!

    Unfortunately tough i'm also an old champ who loves to deal with data outside of React Components, which i think is a lot more zen, zustand style :candy: :lollipop:

    opened by hems 0
  • SWRConfig fetcher does not pass down to useSWRInfinite

    SWRConfig fetcher does not pass down to useSWRInfinite

    Bug report

    Description / Observed Behavior

    I have read and applied the Global Configuration example with SWRConfig and the fetcher. I noticed that useSWR hook works fine without fetcher parameters but useSWRInfinite hook does not

    Expected Behavior

    the official doc stated that The context SWRConfig can provide global configurations (options) for all SWR hooks

    Repro Steps / Code Example

    //this works
    const { data, errorr } = useSWR(url)
    //this doesn't work
    const { data, error } = useSWRInfinite(url)
    //this work
    import { fetcher } from "./contexts/SWRContext"
    const { data, error } = useSWRInfinite(url, fetcher)
    

    Additional Context

    SWR version 2.0.0. Maybe relating to this issues https://github.com/vercel/swr/issues/1899

    opened by demosofa 0
  • Issue with Enums

    Issue with Enums

    Bug report

    Description / Observed Behavior

    I am using SWR in typescript, so basically something like:

    const { data: purchase } = useSWR<Purchase>(`/v3/purchases/${params.id}`;
    // Where purchase.status is a PurchaseStatuses enum, like this:
    
    export enum PurchaseStatuses {
        Live = 0,
        Off = 1
    }
    

    Expected Behavior

    This enum shouldn't be parsed as string, but when I do typeof purchase.status I get a string.

    Also what about next13, does SWR will continues to exists? What is the plan?

    I use the last version of SWR.

    opened by thisisclint21 1
  • When calling useSWR isLoading is always undefined

    When calling useSWR isLoading is always undefined

    Bug report

    isLoading not being set during initial useSWR loading

    Per example on the main page:

    import useSWR from 'swr'
    
    function Profile() {
      const { data, error, isLoading } = useSWR('/api/user', fetcher)
    
      if (error) return <div>failed to load</div>
      if (isLoading) return <div>loading...</div>
      return <div>hello {data.name}!</div>
    }
    

    The field isLoading is used to guard data, so that data.name does not error.

    However the field isLoading is never set, it is always undefined, so the data is never guarded, both isLoading and data are undefined which means that data.name results in an error.

    Expected Behavior

    When using const { data, error, isLoading } = useSWR('/api/user', fetcher) I expected isLoading to be truthy until the fetcher's promise resolves (which could be undefined). After the fetcher resolves I expected isLoading to be falsy suggesting that my code can now access the data object and make interpretations based on the data's state.

    Repro Steps / Code Example

    CodeSandbox

    To produce this code sandbox I combined the first page documentation above with the basic example: https://swr.vercel.app/examples/basic

    I also added a 1 second wait so that the error would be more obvious.

    opened by dodtsair 1
Releases(2.0.0)
  • 2.0.0(Dec 9, 2022)

    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

    • bugfix: make suspense and revalidateIfStale work together by @simowe in https://github.com/vercel/swr/pull/1851
    • feat: support functional optimisticData by @huozhi in https://github.com/vercel/swr/pull/1861
    • test: fix an act warning by @koba04 in https://github.com/vercel/swr/pull/1888
    • breaking: Change the fetcher argument to be consistent with the passed key by @shuding in https://github.com/vercel/swr/pull/1864
    • Keep all fields with one single key by @shuding in https://github.com/vercel/swr/pull/1863
    • fix: wrong spell by @baojie223 in https://github.com/vercel/swr/pull/1902
    • Update React 18 dependencies by @shuding in https://github.com/vercel/swr/pull/1824
    • build(deps): bump minimist from 1.2.5 to 1.2.6 by @dependabot in https://github.com/vercel/swr/pull/1903
    • type: make type inference simpler by @promer94 in https://github.com/vercel/swr/pull/1908
    • type: fix type error on SWRConfig by @Himself65 in https://github.com/vercel/swr/pull/1913
    • feat: Hook for remote mutations by @shuding in https://github.com/vercel/swr/pull/1450
    • Add isFallback state by @shuding in https://github.com/vercel/swr/pull/1925
    • build: output mutation cjs bundle with named exports by @huozhi in https://github.com/vercel/swr/pull/1926
    • Add isLoading state and refactor the core by @shuding in https://github.com/vercel/swr/pull/1928
    • Add keepPreviousData option by @shuding in https://github.com/vercel/swr/pull/1929
    • types: drop legacy types by @huozhi in https://github.com/vercel/swr/pull/1930
    • breaking: Throw error when using suspense on the server side without fallback in React 18 by @shuding in https://github.com/vercel/swr/pull/1931
    • type: extends useConfig cache interface by @promer94 in https://github.com/vercel/swr/pull/1938
    • remove mount check for react18 by @promer94 in https://github.com/vercel/swr/pull/1927
    • lint: dont check unused vars with underscore prefix by @huozhi in https://github.com/vercel/swr/pull/1939
    • test: upgrade to jest 28 by @huozhi in https://github.com/vercel/swr/pull/1942
    • Fix cache types by @chibicode in https://github.com/vercel/swr/pull/1961
    • Improved React 18 support by @promer94 in https://github.com/vercel/swr/pull/1962
    • types: fix type regressions by @promer94 in https://github.com/vercel/swr/pull/1966
    • fix: mutate args for useSWRInfinite hook by @sanjeev29 in https://github.com/vercel/swr/pull/1947
    • build: import with-selector with extension from useESE by @huozhi in https://github.com/vercel/swr/pull/1967
    • Bug fixes by @shuding in https://github.com/vercel/swr/pull/1968
    • chore: Faster type checking by @shuding in https://github.com/vercel/swr/pull/1969
    • fix: try fix codesanbox ci import error by @promer94 in https://github.com/vercel/swr/pull/1971
    • Fix race conditions related to optimistic UI by @shuding in https://github.com/vercel/swr/pull/1970
    • chore: Add test cases for mutate by @shuding in https://github.com/vercel/swr/pull/1976
    • fix: Should always reset to the original data after mutating with optimistic data by @shuding in https://github.com/vercel/swr/pull/1982
    • refactor: remove useless ref copy by @promer94 in https://github.com/vercel/swr/pull/1981
    • chore: switch to pnpm and turborepo by @promer94 in https://github.com/vercel/swr/pull/1983
    • fix: should only update cache when actually start new request by @promer94 in https://github.com/vercel/swr/pull/1986
    • chore: save some bytes by @promer94 in https://github.com/vercel/swr/pull/1991
    • fix: useSWRMutation - clear error after successful trigger (#1973) by @anirudh1713 in https://github.com/vercel/swr/pull/1995
    • Fix typo: getSWRCacahe -> getSWRCache by @sdornan in https://github.com/vercel/swr/pull/2000
    • build: do not abort on watch mode when ts erroring by @huozhi in https://github.com/vercel/swr/pull/1992
    • chore: add engine field to limit pnpm version by @huozhi in https://github.com/vercel/swr/pull/1990
    • test: add test case for #1974 by @promer94 in https://github.com/vercel/swr/pull/2005
    • fix: Adding debounce for autocomplete-suggestions example by @Walkeryr in https://github.com/vercel/swr/pull/2017
    • BREAKING: rename SWRConfig.default to SWRConfig.defaultValue by @huozhi in https://github.com/vercel/swr/pull/2023
    • feat: support functional swr context config by @huozhi in https://github.com/vercel/swr/pull/2024
    • test: fix all act warnings by @koba04 in https://github.com/vercel/swr/pull/2031
    • feat: add preload function by @koba04 in https://github.com/vercel/swr/pull/2026
    • fix: Avoid preloading the resource multiple times by @shuding in https://github.com/vercel/swr/pull/2036
    • fix: isLoading and isValidating should always respect cache value by @promer94 in https://github.com/vercel/swr/pull/2048
    • Fix ts type generation by @huozhi in https://github.com/vercel/swr/pull/2038
    • feat: mutate filter by @huozhi in https://github.com/vercel/swr/pull/1989
    • Fix typos by @hiro0218 in https://github.com/vercel/swr/pull/2052
    • feat: add DevTools hook by @koba04 in https://github.com/vercel/swr/pull/2016
    • Use consistent typing imports by @huozhi in https://github.com/vercel/swr/pull/2061
    • Upgrading use-sync-external-store lib by @sanjaiyan-dev in https://github.com/vercel/swr/pull/2063
    • Revert swr config generic by @huozhi in https://github.com/vercel/swr/pull/2065
    • Fix: raf return type by @huozhi in https://github.com/vercel/swr/pull/2074
    • Remove unused info from dummy package.json by @huozhi in https://github.com/vercel/swr/pull/2083
    • Use pnpm workspace by @huozhi in https://github.com/vercel/swr/pull/2085
    • bump typescript and apply nodenext module resolution by @huozhi in https://github.com/vercel/swr/pull/2084
    • Chore: Typos and grammar by @AllanOliveiraM in https://github.com/vercel/swr/pull/2094
    • chore: add basic tsdoc by @promer94 in https://github.com/vercel/swr/pull/2089
    • types: add generic for SWRInfiniteKeyLoader by @jason89521 in https://github.com/vercel/swr/pull/2104
    • fix: add swr/_internal to paths by @jason89521 in https://github.com/vercel/swr/pull/2105
    • type: make tsconfig simpler and fix type error by @promer94 in https://github.com/vercel/swr/pull/2115
    • chore: exclude .tsbuildinfo from files, reduce install size by @promer94 in https://github.com/vercel/swr/pull/2119
    • Reorder exports conditions by @huozhi in https://github.com/vercel/swr/pull/2130
    • Upgrade bunchee by @huozhi in https://github.com/vercel/swr/pull/2132
    • Bump typescript and assemble pnpm scripts by @huozhi in https://github.com/vercel/swr/pull/2133
    • chore: add github actions reporter by @promer94 in https://github.com/vercel/swr/pull/2131
    • Dedupe installed swc by @huozhi in https://github.com/vercel/swr/pull/2136
    • test: add a test for preload API in effects by @koba04 in https://github.com/vercel/swr/pull/2138
    • test: add more isLoading tests for the case a key is null or an error by @koba04 in https://github.com/vercel/swr/pull/2141
    • ci: use action/setup-node built-in pnpm cache and bump to node16 by @promer94 in https://github.com/vercel/swr/pull/2142
    • test: add tests for dependency collection by @koba04 in https://github.com/vercel/swr/pull/2140
    • chore: bump dev deps by @huozhi in https://github.com/vercel/swr/pull/2143
    • memoize config values to avoid frequent context propagation by @gnoff in https://github.com/vercel/swr/pull/2149
    • Bundle types into one file by @huozhi in https://github.com/vercel/swr/pull/2150
    • Revert target option by @huozhi in https://github.com/vercel/swr/pull/2151
    • chore: fix missing husky warning by @huozhi in https://github.com/vercel/swr/pull/2160
    • Remove downlevelIteration and traverse iterator manually by @huozhi in https://github.com/vercel/swr/pull/2181
    • fix: re-render when returned data and fallbackData is the same and keepPreviousData is enabled by @koba04 in https://github.com/vercel/swr/pull/2169
    • breaking: Change the error broadcasting behavior in mutations and add throwOnError option by @shuding in https://github.com/vercel/swr/pull/2182
    • docs: Add JSDoc comments to useSWRMutation by @shuding in https://github.com/vercel/swr/pull/2183
    • type: export MutationFetcher by @ssssota in https://github.com/vercel/swr/pull/2184
    • Bump bundler by @huozhi in https://github.com/vercel/swr/pull/2187
    • resolve swr internal imports as external by @huozhi in https://github.com/vercel/swr/pull/2225
    • test: update tests alias to swr subpath exports by @huozhi in https://github.com/vercel/swr/pull/2243
    • feat: support functional rollbackOnError by @huozhi in https://github.com/vercel/swr/pull/2242
    • Update build target to es2018 by @shuding in https://github.com/vercel/swr/pull/2249
    • Fix missing esmodule mark in cjs build by @huozhi in https://github.com/vercel/swr/pull/2251
    • fix: pass null fetcher to middleware by @koba04 in https://github.com/vercel/swr/pull/2240

    New Contributors

    • @simowe made their first contribution in https://github.com/vercel/swr/pull/1851
    • @baojie223 made their first contribution in https://github.com/vercel/swr/pull/1902
    • @Himself65 made their first contribution in https://github.com/vercel/swr/pull/1913
    • @chibicode made their first contribution in https://github.com/vercel/swr/pull/1961
    • @sanjeev29 made their first contribution in https://github.com/vercel/swr/pull/1947
    • @sdornan made their first contribution in https://github.com/vercel/swr/pull/2000
    • @Walkeryr made their first contribution in https://github.com/vercel/swr/pull/2017
    • @hiro0218 made their first contribution in https://github.com/vercel/swr/pull/2052
    • @sanjaiyan-dev made their first contribution in https://github.com/vercel/swr/pull/2063
    • @AllanOliveiraM made their first contribution in https://github.com/vercel/swr/pull/2094
    • @jason89521 made their first contribution in https://github.com/vercel/swr/pull/2104
    • @gnoff made their first contribution in https://github.com/vercel/swr/pull/2149
    • @ssssota made their first contribution in https://github.com/vercel/swr/pull/2184

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

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-rc.3(Nov 28, 2022)

    What's Changed

    • Fix missing esmodule mark in cjs build by @huozhi in https://github.com/vercel/swr/pull/2251
    • fix: pass null fetcher to middleware by @koba04 in https://github.com/vercel/swr/pull/2240

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

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-rc.1(Nov 25, 2022)

    ~~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

    • breaking: Update build target to es2018 by @shuding in https://github.com/vercel/swr/pull/2249
    • feat: support functional rollbackOnError by @huozhi in https://github.com/vercel/swr/pull/2242
    • fix: resolve swr internal imports as external by @huozhi in https://github.com/vercel/swr/pull/2225
    • chore: update tests alias to swr subpath exports by @huozhi in https://github.com/vercel/swr/pull/2243
    • chore: export MutationFetcher by @ssssota in https://github.com/vercel/swr/pull/2184
    • chore: Bump bundler by @huozhi in https://github.com/vercel/swr/pull/2187

    New Contributors

    • @ssssota made their first contribution in https://github.com/vercel/swr/pull/2184

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

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-rc.0(Oct 5, 2022)

    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

    • chore: fix missing husky warning by @huozhi in https://github.com/vercel/swr/pull/2160
    • fix: Remove downlevelIteration and traverse iterator manually by @huozhi in https://github.com/vercel/swr/pull/2181
    • fix: re-render when returned data and fallbackData is the same and keepPreviousData is enabled by @koba04 in https://github.com/vercel/swr/pull/2169
    • breaking: Change the error broadcasting behavior in mutations and add throwOnError option by @shuding in https://github.com/vercel/swr/pull/2182
    • docs: Add JSDoc comments to useSWRMutation by @shuding in https://github.com/vercel/swr/pull/2183

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

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-beta.7(Sep 12, 2022)

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

    What's Changed

    • Upgrading use-sync-external-store lib by @sanjaiyan-dev in https://github.com/vercel/swr/pull/2063
    • Revert swr config generic by @huozhi in https://github.com/vercel/swr/pull/2065
    • Fix: raf return type by @huozhi in https://github.com/vercel/swr/pull/2074
    • Remove unused info from dummy package.json by @huozhi in https://github.com/vercel/swr/pull/2083
    • Use pnpm workspace by @huozhi in https://github.com/vercel/swr/pull/2085
    • bump typescript and apply nodenext module resolution by @huozhi in https://github.com/vercel/swr/pull/2084
    • Chore: Typos and grammar by @AllanOliveiraM in https://github.com/vercel/swr/pull/2094
    • chore: add basic tsdoc by @promer94 in https://github.com/vercel/swr/pull/2089
    • types: add generic for SWRInfiniteKeyLoader by @jason89521 in https://github.com/vercel/swr/pull/2104
    • fix: add swr/_internal to paths by @jason89521 in https://github.com/vercel/swr/pull/2105
    • type: make tsconfig simpler and fix type error by @promer94 in https://github.com/vercel/swr/pull/2115
    • chore: exclude .tsbuildinfo from files, reduce install size by @promer94 in https://github.com/vercel/swr/pull/2119
    • Reorder exports conditions by @huozhi in https://github.com/vercel/swr/pull/2130
    • Upgrade bunchee by @huozhi in https://github.com/vercel/swr/pull/2132
    • Bump typescript and assemble pnpm scripts by @huozhi in https://github.com/vercel/swr/pull/2133
    • chore: add github actions reporter by @promer94 in https://github.com/vercel/swr/pull/2131
    • Dedupe installed swc by @huozhi in https://github.com/vercel/swr/pull/2136
    • test: add a test for preload API in effects by @koba04 in https://github.com/vercel/swr/pull/2138
    • test: add more isLoading tests for the case a key is null or an error by @koba04 in https://github.com/vercel/swr/pull/2141
    • ci: use action/setup-node built-in pnpm cache and bump to node16 by @promer94 in https://github.com/vercel/swr/pull/2142
    • test: add tests for dependency collection by @koba04 in https://github.com/vercel/swr/pull/2140
    • chore: bump dev deps by @huozhi in https://github.com/vercel/swr/pull/2143
    • memoize config values to avoid frequent context propagation by @gnoff in https://github.com/vercel/swr/pull/2149
    • Bundle types into one file by @huozhi in https://github.com/vercel/swr/pull/2150
    • Revert target option by @huozhi in https://github.com/vercel/swr/pull/2151

    New Contributors

    • @sanjaiyan-dev made their first contribution in https://github.com/vercel/swr/pull/2063
    • @AllanOliveiraM made their first contribution in https://github.com/vercel/swr/pull/2094
    • @jason89521 made their first contribution in https://github.com/vercel/swr/pull/2104
    • @gnoff made their first contribution in https://github.com/vercel/swr/pull/2149

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

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-beta.6(Jul 4, 2022)

    What's Changed

    • fix: Fix typos by @hiro0218 in https://github.com/vercel/swr/pull/2052
    • feat: Add DevTools hook by @koba04 in https://github.com/vercel/swr/pull/2016
    • fix: Use consistent typing imports by @huozhi in https://github.com/vercel/swr/pull/2061

    New Contributors

    • @hiro0218 made their first contribution in https://github.com/vercel/swr/pull/2052

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

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-beta.5(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

    • feat: Mutate multiple keys by @huozhi in https://github.com/vercel/swr/pull/1989
    • fix: Avoid preloading the resource multiple times by @shuding in https://github.com/vercel/swr/pull/2036
    • fix: isLoading and isValidating should always respect cache value by @promer94 in https://github.com/vercel/swr/pull/2048
    • chore: Fix TS type generation by @huozhi in https://github.com/vercel/swr/pull/2038

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

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-beta.4(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

    • breaking: Rename SWRConfig.default to SWRConfig.defaultValue by @huozhi in https://github.com/vercel/swr/pull/2023
    • feat: Add preload function by @koba04 in https://github.com/vercel/swr/pull/2026
    • feat: Support function as context config by @huozhi in https://github.com/vercel/swr/pull/2024
    • fix: Should always reset to the original data after mutating with optimistic data by @shuding in https://github.com/vercel/swr/pull/1982
    • fix: Should only update cache when actually start new request by @promer94 in https://github.com/vercel/swr/pull/1986
    • fix: useSWRMutation - clear error after successful trigger (#1973) by @anirudh1713 in https://github.com/vercel/swr/pull/1995
    • chore: Adding debounce for autocomplete-suggestions example by @Walkeryr in https://github.com/vercel/swr/pull/2017
    • chore: Remove useless ref copy by @promer94 in https://github.com/vercel/swr/pull/1981
    • chore: Switch to pnpm and turborepo by @promer94 in https://github.com/vercel/swr/pull/1983
    • test: Add test cases for mutate by @shuding in https://github.com/vercel/swr/pull/1976
    • chore: Save some bytes by @promer94 in https://github.com/vercel/swr/pull/1991
    • chore: getSWRCacahe -> getSWRCache by @sdornan in https://github.com/vercel/swr/pull/2000
    • chore: Do not abort on watch mode when ts erroring by @huozhi in https://github.com/vercel/swr/pull/1992
    • chore: Add engine field to limit pnpm version by @huozhi in https://github.com/vercel/swr/pull/1990
    • test: Add test case for #1974 by @promer94 in https://github.com/vercel/swr/pull/2005
    • test: Add test cases for mutate by @shuding in https://github.com/vercel/swr/pull/1976
    • test: Fix all act warnings by @koba04 in https://github.com/vercel/swr/pull/2031

    New Contributors

    • @sdornan made their first contribution in https://github.com/vercel/swr/pull/2000
    • @Walkeryr made their first contribution in https://github.com/vercel/swr/pull/2017

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

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-beta.3(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

    • breaking: Throw error when using suspense on the server side without fallback in React 18 by @shuding in https://github.com/vercel/swr/pull/1931
    • feat: Improved React 18 support by @promer94 in https://github.com/vercel/swr/pull/1962
    • fix: Fix cache types by @chibicode in https://github.com/vercel/swr/pull/1961
    • fix: Remove mount check for react18 by @promer94 in https://github.com/vercel/swr/pull/1927
    • fix: Mutate args for useSWRInfinite hook by @sanjeev29 in https://github.com/vercel/swr/pull/1947
    • fix: Import with-selector with extension from useESE by @huozhi in https://github.com/vercel/swr/pull/1967
    • fix: Bug fixes by @shuding in https://github.com/vercel/swr/pull/1968
    • fix: Fix race conditions related to optimistic UI by @shuding in https://github.com/vercel/swr/pull/1970
    • type: Extends useConfig cache interface by @promer94 in https://github.com/vercel/swr/pull/1938
    • type: Fix type regressions by @promer94 in https://github.com/vercel/swr/pull/1966
    • chore: Don't check unused vars with underscore prefix by @huozhi in https://github.com/vercel/swr/pull/1939
    • chore: Upgrade to jest 28 by @huozhi in https://github.com/vercel/swr/pull/1942
    • chore: Faster type checking by @shuding in https://github.com/vercel/swr/pull/1969
    • chore: Fix codesanbox ci import error by @promer94 in https://github.com/vercel/swr/pull/1971

    New Contributors

    • @chibicode made their first contribution in https://github.com/vercel/swr/pull/1961
    • @sanjeev29 made their first contribution in https://github.com/vercel/swr/pull/1947

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

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-beta.1(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

    • breaking: drop legacy types by @huozhi in https://github.com/vercel/swr/pull/1930
    • feat: isLoading state and refactor the core by @shuding in https://github.com/vercel/swr/pull/1928
    • feat: keepPreviousData option by @shuding in https://github.com/vercel/swr/pull/1929
    • chore: refactoring by @shuding in https://github.com/vercel/swr/pull/1925
    • fix: output mutation cjs bundle with named exports by @huozhi in https://github.com/vercel/swr/pull/1926

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

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-beta.0(Apr 11, 2022)

    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

    • bugfix: make suspense and revalidateIfStale work together by @simowe in https://github.com/vercel/swr/pull/1851
    • feat: support functional optimisticData by @huozhi in https://github.com/vercel/swr/pull/1861
    • test: fix an act warning by @koba04 in https://github.com/vercel/swr/pull/1888
    • breaking: Change the fetcher argument to be consistent with the passed key by @shuding in https://github.com/vercel/swr/pull/1864
    • Keep all fields with one single key by @shuding in https://github.com/vercel/swr/pull/1863
    • fix: wrong spell by @baojie223 in https://github.com/vercel/swr/pull/1902
    • Update React 18 dependencies by @shuding in https://github.com/vercel/swr/pull/1824
    • build(deps): bump minimist from 1.2.5 to 1.2.6 by @dependabot in https://github.com/vercel/swr/pull/1903
    • type: make type inference simpler by @promer94 in https://github.com/vercel/swr/pull/1908
    • type: fix type error on SWRConfig by @Himself65 in https://github.com/vercel/swr/pull/1913
    • feat: Hook for remote mutations by @shuding in https://github.com/vercel/swr/pull/1450

    New Contributors

    • @simowe made their first contribution in https://github.com/vercel/swr/pull/1851
    • @baojie223 made their first contribution in https://github.com/vercel/swr/pull/1902
    • @Himself65 made their first contribution in https://github.com/vercel/swr/pull/1913

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

    Source code(tar.gz)
    Source code(zip)
  • 1.3.0(Apr 10, 2022)

    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

    Source code(tar.gz)
    Source code(zip)
  • 1.2.2(Feb 18, 2022)

    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 https://github.com/vercel/swr/pull/1837
    • fix: reset stale unmountedRef in suspense by @promer94 in https://github.com/vercel/swr/pull/1843
    • test: add a test for the behavior of revalidateOnMount when the key has been changed by @koba04 in https://github.com/vercel/swr/pull/1847
    • feat: Support populateCache as a function by @shuding in https://github.com/vercel/swr/pull/1818

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

    Source code(tar.gz)
    Source code(zip)
  • 1.2.1(Feb 2, 2022)

    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 https://github.com/vercel/swr/pull/1816
    • build(deps-dev): bump next from 12.0.8 to 12.0.9 by @dependabot in https://github.com/vercel/swr/pull/1821
    • fix: useSWRInfinite revalidates with revalidateOnMount by @koba04 in https://github.com/vercel/swr/pull/1830

    New Contributors

    • @sairajchouhan made their first contribution in https://github.com/vercel/swr/pull/1816

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

    Source code(tar.gz)
    Source code(zip)
  • 1.2.0(Jan 26, 2022)

    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

    • feat: Optimistic mutation with error rollback by @shuding in https://github.com/vercel/swr/pull/1745
    • fix: Required return type when mutating by @RKatarine in https://github.com/vercel/swr/pull/1772
    • fix: use the latest reference of fetcher with suspense mode by @koba04 in https://github.com/vercel/swr/pull/1803
    • test: add delay for flaky focus test by @huozhi in https://github.com/vercel/swr/pull/1762
    • test: remove flaky focus test case by @huozhi in https://github.com/vercel/swr/pull/1793
    • test: use @swc/jest by @huozhi in https://github.com/vercel/swr/pull/1790
    • chore: Ignore coverage report by @shuding in https://github.com/vercel/swr/pull/1744
    • chore: Merge mutation states by @shuding in https://github.com/vercel/swr/pull/1748
    • chore: Rename CONCURRENT_REQUESTS to FETCH by @shuding in https://github.com/vercel/swr/pull/1749
    • chore: Merge extra request states in cache by @shuding in https://github.com/vercel/swr/pull/1752
    • chore: support mjs exports by @huozhi in https://github.com/vercel/swr/pull/1760
    • chore: remove useless react-native field by @huozhi in https://github.com/vercel/swr/pull/1761
    • chore: comment helper by @huozhi in https://github.com/vercel/swr/pull/1757
    • chore: display name in devtool by @huozhi in https://github.com/vercel/swr/pull/1779
    • chore: simplify example development by @huozhi in https://github.com/vercel/swr/pull/1787
    • chore: build: improve watch commands by @huozhi in https://github.com/vercel/swr/pull/1788
    • chore: Update examples and dependencies by @shuding in https://github.com/vercel/swr/pull/1789
    • chore: zeit -> vercel by @huozhi in https://github.com/vercel/swr/pull/1791
    • chore: Clean up configurations by @shuding in https://github.com/vercel/swr/pull/1792
    • chore: move community health files to .github dir by @huozhi in https://github.com/vercel/swr/pull/1794
    • chore: Add link to security email directly by @huozhi in https://github.com/vercel/swr/pull/1795

    New Contributors

    • @RKatarine made their first contribution in https://github.com/vercel/swr/pull/1772

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

    Source code(tar.gz)
    Source code(zip)
  • 1.2.0-beta.1(Jan 12, 2022)

    What's Changed

    • doc: comment helper by @huozhi in https://github.com/vercel/swr/pull/1757
    • build: support mjs exports by @huozhi in https://github.com/vercel/swr/pull/1760
    • chore: remove useless react-native field by @huozhi in https://github.com/vercel/swr/pull/1761
    • test: add delay for flaky focus test by @huozhi in https://github.com/vercel/swr/pull/1762
    • Required return type when mutating by @RKatarine in https://github.com/vercel/swr/pull/1772
    • polish: display name in devtool by @huozhi in https://github.com/vercel/swr/pull/1779

    New Contributors

    • @RKatarine made their first contribution in https://github.com/vercel/swr/pull/1772

    Full Changelog: https://github.com/vercel/swr/compare/1.1.2...1.2.0-beta.1

    Source code(tar.gz)
    Source code(zip)
  • 1.2.0-beta.0(Dec 28, 2021)

    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

    • feat: Optimistic mutation with error rollback by @shuding in https://github.com/vercel/swr/pull/1745
    • chore: Ignore coverage report by @shuding in https://github.com/vercel/swr/pull/1744
    • chore: Merge mutation states by @shuding in https://github.com/vercel/swr/pull/1748
    • chore: Rename CONCURRENT_REQUESTS to FETCH by @shuding in https://github.com/vercel/swr/pull/1749
    • Merge extra request states in cache by @shuding in https://github.com/vercel/swr/pull/1752

    Full Changelog: https://github.com/vercel/swr/compare/1.1.2...1.2.0-beta.0

    Source code(tar.gz)
    Source code(zip)
  • 1.1.2(Dec 26, 2021)

    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 https://github.com/vercel/swr/pull/1707
    • type(infinite): export SWRInfinteHook and SWRInfiniteKeyLoader from infinite, rename InfiniteFetcher to SWRInfiniteFetcher by @houkanshan in https://github.com/vercel/swr/pull/1714
    • feat: Ensure auto revalidations are executed after state updates by @shuding in https://github.com/vercel/swr/pull/1720
    • Add moduleNameMapper to jest by @shuding in https://github.com/vercel/swr/pull/1724
    • Improve test by @promer94 in https://github.com/vercel/swr/pull/1725
    • feat: Use the latest reference of fetcher by @shuding in https://github.com/vercel/swr/pull/1727
    • fix: Re-export InfiniteFetcher by @shuding in https://github.com/vercel/swr/pull/1728
    • feat: Add populateCache option to mutate by @shuding in https://github.com/vercel/swr/pull/1729
    • Fix local state sharing example deps by @huozhi in https://github.com/vercel/swr/pull/1737
    • Merge states for concurrent requests by @shuding in https://github.com/vercel/swr/pull/1741
    • Skip error retrying when document is not active and improve tests by @shuding in https://github.com/vercel/swr/pull/1742

    New Contributors

    • @thomaspaulmann made their first contribution in https://github.com/vercel/swr/pull/1707
    • @houkanshan made their first contribution in https://github.com/vercel/swr/pull/1714

    Full Changelog: https://github.com/vercel/swr/compare/1.1.1...1.1.2

    Source code(tar.gz)
    Source code(zip)
  • 1.1.2-beta.1(Dec 23, 2021)

    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

    • type(infinite): export SWRInfinteHook and InfiniteKeyLoader from infinite by @houkanshan in https://github.com/vercel/swr/pull/1714
    • feat: Ensure auto revalidations are executed after state updates by @shuding in https://github.com/vercel/swr/pull/1720
    • Add moduleNameMapper to jest by @shuding in https://github.com/vercel/swr/pull/1724
    • Improve test by @promer94 in https://github.com/vercel/swr/pull/1725
    • feat: Use the latest reference of fetcher by @shuding in https://github.com/vercel/swr/pull/1727

    New Contributors

    • @houkanshan made their first contribution in https://github.com/vercel/swr/pull/1714

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

    Source code(tar.gz)
    Source code(zip)
  • 1.1.2-beta.0(Dec 15, 2021)

    What's Changed

    • Make polyfill for requestAnimationFrame more robust by @thomaspaulmann in https://github.com/vercel/swr/pull/1707

    New Contributors

    • @thomaspaulmann made their first contribution in https://github.com/vercel/swr/pull/1707

    Full Changelog: https://github.com/vercel/swr/compare/1.1.1...1.1.2-beta.0

    Source code(tar.gz)
    Source code(zip)
  • 1.1.1(Dec 10, 2021)

    Highlights of This Release

    Dynamic refreshInterval

    You can now pass a function as refreshInterval, to dynamically return the interval (in millisecond) til the next request, based on the current data:

    useSWR('key', fetcher, {
      refreshInterval: function (data: Data | undefined) {
        if (!data) return 3000 // Initial request 
        return data.next_update
      }
    })
    

    If return 0, polling will be stopped.

    What's Changed

    • feat: refreshInterval as a function by @Andrewnt219 in https://github.com/vercel/swr/pull/1690
    • test: add refreshInterval function returns 0 by @Andrewnt219 in https://github.com/vercel/swr/pull/1691
    • fix: If newData is deeply to the latest state, broadcast the latest state by @icyJoseph in https://github.com/vercel/swr/pull/1697
    • fix: Return undefined data if key's falsy under suspense mode by @icyJoseph in https://github.com/vercel/swr/pull/1698

    New Contributors

    • @Andrewnt219 made their first contribution in https://github.com/vercel/swr/pull/1690
    • @icyJoseph made their first contribution in https://github.com/vercel/swr/pull/1697

    Full Changelog: https://github.com/vercel/swr/compare/1.1.0...1.1.1

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Nov 30, 2021)

    Highlights for This Release

    1. Built-in & stable serialization for SWR keys

    useSWR({ query: graphql`...`, variables }, fetcher)
    useSWR({ query: graphql`...`, variables }, fetcher)
    useSWR({ variables, query: graphql`...` }, fetcher)
    // ^all recognized as the same resource
    

    For array keys too, it's safe to do the following:

    useSWR([ `...`, { variables } ], fetcher)
    

    2. revalidateFirstPage for useSWRInfinite

    This is a new added option for useSWRInfinite (defaults to true), you can use it to control if the first page should be revalidated when changing the size or doing a mutation.

    3. Better TypeScript support

    • Key / arguments
    • Conditional / dependent
    • Constant keys
    • Returned data

    image

    What's Changed

    • Feature: make return state(data, error and isValidating) readonly by @anirudh1713 in https://github.com/vercel/swr/pull/1431
    • Stable hash by @shuding in https://github.com/vercel/swr/pull/1429
    • test: add render utilities and remove TestSWRConfig by @koba04 in https://github.com/vercel/swr/pull/1435
    • Revert "Feature: make return state(data, error and isValidating) readonly" by @huozhi in https://github.com/vercel/swr/pull/1443
    • Fix initial isValidating when isPaused() returns true by @anothertempore in https://github.com/vercel/swr/pull/1440
    • build: no emit on error by @huozhi in https://github.com/vercel/swr/pull/1446
    • chore: remove unused typings by @huozhi in https://github.com/vercel/swr/pull/1448
    • enhance: provider release handlers by @huozhi in https://github.com/vercel/swr/pull/1449
    • test: refactor use-swr-cache-test by @koba04 in https://github.com/vercel/swr/pull/1442
    • Chore: refactor code related to unsubscribing global listeners by @shuding in https://github.com/vercel/swr/pull/1451
    • Chore: code refactoring for swr/infinite by @shuding in https://github.com/vercel/swr/pull/1452
    • test: refactor concurrent rendering tests by @koba04 in https://github.com/vercel/swr/pull/1457
    • test: refactor config tests by @koba04 in https://github.com/vercel/swr/pull/1458
    • Revert "feat: add a warning for invalid arguments with suspense mode … by @koba04 in https://github.com/vercel/swr/pull/1460
    • test: refactor mutation tests by @koba04 in https://github.com/vercel/swr/pull/1459
    • fix: Support IE11 by @amannn in https://github.com/vercel/swr/pull/1463
    • test: refactor immutable and infinite hook tests by @koba04 in https://github.com/vercel/swr/pull/1466
    • chore: Add React 18 to peerDependencies by @shuding in https://github.com/vercel/swr/pull/1467
    • test: refactor integration and loading tests by @koba04 in https://github.com/vercel/swr/pull/1473
    • test: refactor key, middlewares, and suspense tests by @koba04 in https://github.com/vercel/swr/pull/1474
    • test: refactor offline and refresh tests by @koba04 in https://github.com/vercel/swr/pull/1483
    • build(deps): bump tmpl from 1.0.4 to 1.0.5 by @dependabot in https://github.com/vercel/swr/pull/1484
    • Upgrade typescript to 4.4.3 by @huozhi in https://github.com/vercel/swr/pull/1486
    • chore: Code refactoring by @shuding in https://github.com/vercel/swr/pull/1482
    • ci: multiple dir type checking by @huozhi in https://github.com/vercel/swr/pull/1492
    • Type useSWR fetcher by @promer94 in https://github.com/vercel/swr/pull/1477
    • chore: Improve project file structure by @shuding in https://github.com/vercel/swr/pull/1497
    • chore: Refine type interfaces by @shuding in https://github.com/vercel/swr/pull/1496
    • chore: Upgrade eslint and add local cache by @shuding in https://github.com/vercel/swr/pull/1499
    • fix: Invalidate the key when mutating without revalidating by @shuding in https://github.com/vercel/swr/pull/1498
    • example: add ref checking condition by @huozhi in https://github.com/vercel/swr/pull/1504
    • fix: Refactor core revalidate function and fix isValidating state bug by @shuding in https://github.com/vercel/swr/pull/1493
    • chore: remove duplicate configs by @huozhi in https://github.com/vercel/swr/pull/1507
    • typing: fix-type-generation by @promer94 in https://github.com/vercel/swr/pull/1509
    • chroe: use yalc for local development by @promer94 in https://github.com/vercel/swr/pull/1508
    • chore: Code refactoring by @shuding in https://github.com/vercel/swr/pull/1521
    • feat: Add new onDiscarded option by @shuding in https://github.com/vercel/swr/pull/1523
    • fix: Error events should be deduplicated by @shuding in https://github.com/vercel/swr/pull/1522
    • chore: Output test code coverage by @shuding in https://github.com/vercel/swr/pull/1511
    • chore: Mark returned states and mutate callback argument as readonly by @shuding in https://github.com/vercel/swr/pull/1514
    • test: Add tests for reconnect and merge-config by @shuding in https://github.com/vercel/swr/pull/1530
    • fix: Only trigger the success event if not discarded by @shuding in https://github.com/vercel/swr/pull/1529
    • chore: Code refactoring by @shuding in https://github.com/vercel/swr/pull/1533
    • Add revalidateFirstPage option to swr/infinite (#1401) by @timas130 in https://github.com/vercel/swr/pull/1538
    • fix: Reusing cache provider by @shuding in https://github.com/vercel/swr/pull/1539
    • chore: fix ts comments by @huozhi in https://github.com/vercel/swr/pull/1540
    • fix: Ensure mutate accepts undefined as the data by @shuding in https://github.com/vercel/swr/pull/1515
    • chore: Fix comment and startAt type by @shuding in https://github.com/vercel/swr/pull/1541
    • chore: Refactor cleanupState by @shuding in https://github.com/vercel/swr/pull/1544
    • feat: using latest version of axios with fetch interceptor by @danestves in https://github.com/vercel/swr/pull/1548
    • test: Add test case for mutation deduplication by @shuding in https://github.com/vercel/swr/pull/1549
    • test: speed up with @swc-node/jest by @huozhi in https://github.com/vercel/swr/pull/1569
    • chore: Optimizations by @shuding in https://github.com/vercel/swr/pull/1578
    • fix react-native issue by @aFINKndreas in https://github.com/vercel/swr/pull/1583
    • fix: Support for functions that return false by @TakahiroHimi in https://github.com/vercel/swr/pull/1586
    • fix: adds undefined as valid Key type to allow falsy Key or Key() by @morgs32 in https://github.com/vercel/swr/pull/1594
    • fix: can't find variable removeEventListener by @zhaomengfan in https://github.com/vercel/swr/pull/1595
    • Revert "chore: Mark returned states and mutate callback argument as readonly" by @shuding in https://github.com/vercel/swr/pull/1570
    • fix: change config alteration process in withMiddleware to be immutable by @junsushin-dev in https://github.com/vercel/swr/pull/1556
    • fix: Allow empty mutate argument list for infinite by @shuding in https://github.com/vercel/swr/pull/1602
    • chore: Add type: "module" and use .mjs extension by @shuding in https://github.com/vercel/swr/pull/1604
    • Revert "chore: Add type: "module" and use .mjs extension (#1604)" by @huozhi in https://github.com/vercel/swr/pull/1618
    • enhance: bind removeEventListener by @huozhi in https://github.com/vercel/swr/pull/1596
    • fix: typos by @nguyenyou in https://github.com/vercel/swr/pull/1647
    • build: output without minification by @huozhi in https://github.com/vercel/swr/pull/1650
    • Tweak types by @promer94 in https://github.com/vercel/swr/pull/1640
    • fix: supports ssr in ie11(#1657) by @Sh031224 in https://github.com/vercel/swr/pull/1659
    • type: disbale inference when data generic is provided by @promer94 in https://github.com/vercel/swr/pull/1658
    • chore: rename major branch to main by @huozhi in https://github.com/vercel/swr/pull/1664
    • fix keyloader index and previousPageData type by @promer94 in https://github.com/vercel/swr/pull/1669
    • Add defaults for SWRResponse by @TakahiroHimi in https://github.com/vercel/swr/pull/1609
    • example: update typescript examples with strict ts mode by @huozhi in https://github.com/vercel/swr/pull/1673
    • chore: upgrade eslint to v8 and prettier to v2 by @huozhi in https://github.com/vercel/swr/pull/1674
    • fix: remove unnecessary async by @Cut0 in https://github.com/vercel/swr/pull/1676
    • types: remove duplicated typing def by @huozhi in https://github.com/vercel/swr/pull/1675
    • chore: Add test case for getKey in useSWRInfinite by @shuding in https://github.com/vercel/swr/pull/1681

    New Contributors

    • @willheslam made their first contribution in https://github.com/vercel/swr/pull/1393
    • @louisgv made their first contribution in https://github.com/vercel/swr/pull/1406
    • @origin-master made their first contribution in https://github.com/vercel/swr/pull/1409
    • @anirudh1713 made their first contribution in https://github.com/vercel/swr/pull/1431
    • @amannn made their first contribution in https://github.com/vercel/swr/pull/1463
    • @timas130 made their first contribution in https://github.com/vercel/swr/pull/1538
    • @danestves made their first contribution in https://github.com/vercel/swr/pull/1548
    • @aFINKndreas made their first contribution in https://github.com/vercel/swr/pull/1583
    • @TakahiroHimi made their first contribution in https://github.com/vercel/swr/pull/1586
    • @zhaomengfan made their first contribution in https://github.com/vercel/swr/pull/1595
    • @junsushin-dev made their first contribution in https://github.com/vercel/swr/pull/1556
    • @nguyenyou made their first contribution in https://github.com/vercel/swr/pull/1647
    • @Sh031224 made their first contribution in https://github.com/vercel/swr/pull/1659
    • @Cut0 made their first contribution in https://github.com/vercel/swr/pull/1676

    Full Changelog: https://github.com/vercel/swr/compare/1.0.1...1.1.0

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0-beta.12(Nov 26, 2021)

    Patches

    • Chore: rename major branch to main: #1664
    • Fix keyloader index and previousPageData type: #1669
    • Fix: Add defaults for SWRResponse: #1609

    Credits

    Huge thanks to @huozhi, @promer94, and @TakahiroHimi for helping!

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0-beta.11(Nov 24, 2021)

    Patches

    • Fix: supports ssr in ie11(#1657): #1659
    • Type: disbale inference when data generic is provided: #1658

    Credits

    Huge thanks to @Sh031224 and @promer94 for helping!

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0-beta.10(Nov 23, 2021)

    Minor Changes

    • Build: output without minification: #1650
    • Tweak types: #1640

    Patches

    • Fix: typos: #1647

    Credits

    Huge thanks to @promer94, @huozhi, and @nguyenyou for helping!

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0-beta.9(Nov 11, 2021)

    Minor Changes

    • Revert "chore: Add type: "module" and use .mjs extension" (#1618): #1604

    Patches

    • Enhance: bind removeEventListener: #1596

    Credits

    Huge thanks to @huozhi for helping!

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0-beta.8(Nov 1, 2021)

  • 1.1.0-beta.7(Nov 1, 2021)

    Minor Changes

    • Fix: Support for functions that return false: #1586
    • Fix: adds undefined as valid Key type to allow falsy Key or Key(): #1594
    • Revert "mark data and error as readonly " (#1570): #1514

    Patches

    • Fix react-native issue: #1583
    • Fix: compatible with miniprogram: #1595
    • Change config alteration process in withMiddleware to be immutable: #1556
    • Fix mutate argument for infinite: #1602

    Credits

    Huge thanks to @TakahiroHimi, @morgs32, @aFINKndreas, @zhaomengfan, and @junsushin-dev for helping!

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0-beta.6(Oct 24, 2021)

    Patches

    • Small fixes: #1541
    • Chore: Refactor cleanupState: #1544
    • Feat: using latest version of axios with fetch interceptor: #1548
    • Test: Add test case for mutation deduplication: #1549
    • Test: speed up with @swc-node/jest: #1569
    • Optimizations: #1578

    Credits

    Huge thanks to @danestves and @huozhi for helping!

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0-beta.5(Oct 9, 2021)

    Minor Changes

    • Mark data and error as readonly: #1514
    • Add revalidateFirstPage option to infinite: #1538

    Patches

    • Output code coverage: #1511
    • Test: Add tests for reconnect and merge-config: #1530
    • Fix: Only trigger the success event if not discarded: #1529
    • Chore: Code refactoring: #1533
    • Fix: Reusing cache provider: #1539
    • Chore: fix ts comments: #1540
    • Fix: Ensure mutate accepts undefined as the data: #1515

    Credits

    Huge thanks to @timas130 and @huozhi for helping!

    Source code(tar.gz)
    Source code(zip)
Owner
Vercel
Develop. Preview. Ship. Creators of Next.js.
Vercel
Ts-api - This is a Typescript library facilitating usage of Localazy's API.

@localazy/ts-api This is a Typescript library facilitating usage of Localazy's API. To better understand this library, it is recommended to study the

Localazy 2 Jun 17, 2022
React Hooks library for remote data fetching

Introduction swr.vercel.app SWR is a React Hooks library for remote data fetching. The name “SWR” is derived from stale-while-revalidate, a cache inva

Vercel 25.2k Jan 8, 2023
⚛️ Hooks for fetching, caching and updating asynchronous data in React

Hooks for fetching, caching and updating asynchronous data in React Enjoy this library? Try the entire TanStack! React Table, React Form, React Charts

Tanner Linsley 32.1k Jan 9, 2023
⚛️ Hooks for fetching, caching and updating asynchronous data in React

Hooks for fetching, caching and updating asynchronous data in React Enjoy this library? Try the entire TanStack! React Table, React Form, React Charts

Tanner Linsley 32k Dec 31, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
Wen? Now! A library to simplify your Web3 data fetching.

Wen Connect? Now! Minimalistic library for Web3 user interfaces. Seamless connection flows to Metamask. Stateless sessions that work anywhere (client,

Guillaume Bibeau-laviolette 20 Jul 20, 2022
local storage wrapper for both react-native and browser. Support size controlling, auto expiring, remote data auto syncing and getting batch data in one query.

react-native-storage This is a local storage wrapper for both react native apps (using AsyncStorage) and web apps (using localStorage). ES6 syntax, pr

Sunny Luo 2.9k Dec 16, 2022
Stale-while-revalidate data fetching for Vue

swrv swrv (pronounced "swerve") is a library using the @vue/composition-api for remote data fetching. It is largely a port of swr. Documentation The n

Kong 1.8k Dec 29, 2022
A Cloudflare Worker for fetching data from Twitter User API.

cloudflare-worker-twitter This is a Cloudflare Worker for fetching data from Twitter User API. ❔ About this project I created this Worker to hide my A

Arda Soytürk 12 Oct 1, 2022
Fetching data from REST COUNTRIES API, this app (mobile version for now) gives information like area, population, capital, and borders for 195 countries from seven continents.

Space Travellers' Hub World Countries App works with an API which returns informations about 195 countries. Fetching data from REST COUNTRIES API, thi

Nicolae Pop 7 Aug 8, 2022
A JavaScript library for EASILY fetching info from TheMovieDB API with support for torrent file names.

TheMovieDB-API-Wrapper.js A easy to use, pure vanilla JavaScript API wrapper for TheMovieDB Show your support! A JavaScript library for easily fetchin

Marketing Pipeline 5 Dec 2, 2022
📋 React Hooks for forms validation (Web + React Native)

English | 繁中 | 简中 | 日本語 | 한국어 | Français | Italiano | Português | Español | Русский | Deutsch | Türkçe Features Built with performance and DX in mind

React Hook Form 32.4k Dec 29, 2022
This Login Form made using React hooks , React Js , Css, Json. This form have 3 inputs, it also validate those inputs & it also having length limitations.

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Yogesh Sharma 0 Jan 3, 2022
React components and hooks for creating VR/AR applications with @react-three/fiber

@react-three/xr React components and hooks for creating VR/AR applications with @react-three/fiber npm install @react-three/xr These demos are real,

Poimandres 1.4k Jan 4, 2023
Minimal Typescript / NextJS dApp template bootstrapped with wagmi Ethereum react hooks library.

Welcome to the NextJS wagmi starter template ?? Looking to get up and running with a Typescript / NextJS dApp as quickly as possible? You're in the ri

Seth 78 Jan 4, 2023
Simple weather app written in HTML, CSS, and JavaScript using the OpenWeather API for fetching weather and geolocation information

Description Simple weather app written in HTML, CSS, and JavaScript using the OpenWeather API for fetching weather and geolocation information. Acknow

Gleb Korzan 4 Feb 23, 2022
A crawler that crawls the site's internal links, fetching information of interest to any SEO specialist to perform appropriate analysis on the site.

Overview ?? It is a module that crawls sites and extracts basic information on any web page of interest to site owners in general, and SEO specialists

Yazan Zoghbi 2 Apr 22, 2022
A crawler that crawls the site's internal links, fetching information of interest to any SEO specialist to perform appropriate analysis on the site.

Overview ?? It is a module that crawls sites and extracts basic information on any web page of interest to site owners in general, and SEO specialists

Yazan Zoghbi 2 Apr 22, 2022