Swr: Cancel requests

Created on 16 Nov 2019  路  7Comments  路  Source: vercel/swr

There are often times in a web application where you need to send a request for the latest user interaction. We need a way to prevent subsequent (async) logic from running for all but the most recent request 鈥撀爏omething like Axios' cancel token or fetch()'s AbortController.

discussion feature request

Most helpful comment

For now a custom hook can (partially) solve it:

function useCancelableSWR (key, opts) {
  const controller = new AbortController()
  return [useSWR(key, url => fetch(url, { signal: controller.signal }), opts), controller]
}

// to use it:
const [{ data }, controller] = useCancelableSWR('/api')
// ...
controller.abort()

(also mentioned in #159)

All 7 comments

The hardest part about this is that every library has its own API. You can pass a controller to the fetch function but there鈥檚 no general way to do it inside SWR. And another question is when to cancel it (when unmounting a component?).

I think it鈥檚 way easier to ignore the result than cancel it with the current state of fetching libraries

For now a custom hook can (partially) solve it:

function useCancelableSWR (key, opts) {
  const controller = new AbortController()
  return [useSWR(key, url => fetch(url, { signal: controller.signal }), opts), controller]
}

// to use it:
const [{ data }, controller] = useCancelableSWR('/api')
// ...
controller.abort()

(also mentioned in #159)

You probably don't want to memoize the AbortController.

You can only abort a controller instance once, so a new request requires a new controller.

Another thing to note is that useMemo is a performance optimization with no hard guarantee that it won't be recalculated. React can choose to recalculate memoized values (https://reactjs.org/docs/hooks-reference.html#usememo).

@strothj The issue is not whether the AbortController instance is properly cached or not. The abort controller should not be cached at all.

I did this with axios

function useCancellableSWR(key, swrOptions) {
  const source = axios.CancelToken.source();

    return [
    useSWR(key, (url) => axios.get(url, { cancelToken: source.token }).then(res => res.data), {
        ...swrOptions,
    }),
    source,
    ];
}

// usage:
const [{ data }, cancelFn] = useCancellableSWR('/endpoint');

cancelFn.cancel()
Was this page helpful?
0 / 5 - 0 ratings

Related issues

bywo picture bywo  路  4Comments

nainardev picture nainardev  路  4Comments

DoT214 picture DoT214  路  4Comments

tiagocorreiaalmeida picture tiagocorreiaalmeida  路  3Comments

needcaffeine picture needcaffeine  路  3Comments