Retry on error

You can use useRetry to retry on error using the exponential backoff algorithm.

useRetry(query, { init: 1000, base: 2, max: 3 })

About

Exponential backoff algorithm allows you to retry fetching a resource if an error is thrown, but on a increasing interval using a geometric progression.

So basically, it will wait init * (base ** count) milliseconds between each retry, where count is the number of retries, until count is equal to max.

Example

With { init: 1000, base: 2, max: 3 }:

  1. First retry will wait 1000 * (2 ** 0) = 1000 ms
  2. Second retry will wait 1000 * (2 ** 1) = 2000 ms
  3. Third retry will wait 1000 * (2 ** 2) = 4000 ms

You can see that the interval is multiplied by 2 (our base) for each retry.

With max = 4, the fourth retry would wait 8000 milliseconds.

Warning

The count is reset when a retry succeeds.

Usage example

function useFetchAndRetryMixture(query: Query) {
useFetch(query)
useRetry(query, { init: 1000, base: 2, max: 3 })
}

Implementation

export interface RetryOptions {
init?: number
base?: number
max?: number
}
export function useRetry(query: Query, options: RetryOptions = {}) {
const { refetch, error, time } = query
const { init = 1000, base = 2, max = 3 } = options
const count = useRef(0)
useEffect(() => {
count.current = 0
}, [refetch])
useEffect(() => {
if (error === undefined) {
count.current = 0
return
}
if (count.current >= max) return
const ratio = base ** count.current
const f = () => { count.current++; refetch() }
const t = setTimeout(f, init * ratio)
return () => clearTimeout(t)
}, [error, time, refetch])
}

See also