Skip to content
On this page

useFetch

Category
Last Changed
6 days ago

Reactive Fetch API provides the ability to abort requests, intercept requests before they are fired, automatically refetch requests when the url changes, and create your own useFetchwith predefined options.

Demo

The following URLs can be used to test different features of useFetch
Normal Request: https://httpbin.org/get
Abort Request: https://httpbin.org/delay/10
Response Error: http://httpbin.org/status/500
isFinished: false
isFetching: false
canAbort: false
statusCode: null
error: null
data: null

Usage

Basic Usage

The useFetchfunction can be used by simply providing a url. The url can be either a string or a ref. The data object will contain the result of the request, the error object will contain any errors, and the isFetching object will indicate if the request is loading.

import { useFetch } from '@vueuse/core'

const { isFetching, error, data } = useFetch(url)
import { useFetch } from '@vueuse/core'

const { isFetching, error, data } = useFetch(url)

Asynchronous Usage

useFetchcan also be awaited just like a normal fetch. Note that whenever a component is asynchronous, whatever component that uses it must wrap the component in a <Suspense> tag. You can read more about the suspense api in the Offical Vue 3 Docs

import { useFetch } from '@vueuse/core'

const { isFetching, error, data } = await useFetch(url)
import { useFetch } from '@vueuse/core'

const { isFetching, error, data } = await useFetch(url)

Refetching on URL change

Using a ref for the url parameter will allow the useFetchfunction to automatically trigger another request when the url is changed.

const url = ref('https://my-api.com/user/1') 

const { data } = useFetch(url, { refetch: true })

url.value = 'https://my-api.com/user/2' // Will trigger another request
const url = ref('https://my-api.com/user/1') 

const { data } = useFetch(url, { refetch: true })

url.value = 'https://my-api.com/user/2' // Will trigger another request

Prevent request from firing immediately

Setting the immediate option to false will prevent the request from firing until the execute function is called.

const { execute } = useFetch(url, { immediate: false })

execute()
const { execute } = useFetch(url, { immediate: false })

execute()

Aborting a request

A request can be aborted by using the abort function from the useFetchfunction. The canAbort property indicates if the request can be aborted.

const { abort, canAbort } = useFetch(url)

setTimeout(() => {
  if (canAbort.value)
    abort()
}, 100)
const { abort, canAbort } = useFetch(url)

setTimeout(() => {
  if (canAbort.value)
    abort()
}, 100)

A request can also be aborted automatically by using timeout property. It will call abort function when the given timeout is reached.

const { data } = useFetch(url, { timeout: 100 })
const { data } = useFetch(url, { timeout: 100 })

Intercepting a request

The beforeFetch option can intercept a request before it is sent and modify the request options and url.

const { data } = useFetch(url, {
  async beforeFetch({ url, options, cancel }) {
    const myToken = await getMyToken()

    if (!myToken)
      cancel()

    options.headers = {
      ...options.headers,
      Authorization: `Bearer ${myToken}`,
    }

    return {
      options
    }
  }
})
const { data } = useFetch(url, {
  async beforeFetch({ url, options, cancel }) {
    const myToken = await getMyToken()

    if (!myToken)
      cancel()

    options.headers = {
      ...options.headers,
      Authorization: `Bearer ${myToken}`,
    }

    return {
      options
    }
  }
})

The afterFetch option can intercept the response data before it is updated.

const { data } = useFetch(url, {
  afterFetch(ctx) {
    if (ctx.data.title === 'HxH')
      ctx.data.title = 'Hunter x Hunter' // Modifies the response data

    return ctx
  },
})
const { data } = useFetch(url, {
  afterFetch(ctx) {
    if (ctx.data.title === 'HxH')
      ctx.data.title = 'Hunter x Hunter' // Modifies the response data

    return ctx
  },
})

The onFetchError option can intercept the response data and error before it is updated.

const { data } = useFetch(url, {
  onFetchError(ctx) {
    // ctx.data can be null when 5xx response
    if (ctx.data === null) 
      ctx.data = { title: 'Hunter x Hunter' } // Modifies the response data

    ctx.error = new Error('Custom Error') // Modifies the error

    return ctx
  }
})
const { data } = useFetch(url, {
  onFetchError(ctx) {
    // ctx.data can be null when 5xx response
    if (ctx.data === null) 
      ctx.data = { title: 'Hunter x Hunter' } // Modifies the response data

    ctx.error = new Error('Custom Error') // Modifies the error

    return ctx
  }
})

Setting the request method and return type

The request method and return type can be set by adding the appropriate methods to the end of useFetch

// Request will be sent with GET method and data will be parsed as JSON
const { data } = useFetch(url).get().json()

// Request will be sent with POST method and data will be parsed as text
const { data } = useFetch(url).post().text()

// Or set the method using the options

// Request will be sent with GET method and data will be parsed as blob
const { data } = useFetch(url, { method: 'GET' }, { refetch: true }).blob()
// Request will be sent with GET method and data will be parsed as JSON
const { data } = useFetch(url).get().json()

// Request will be sent with POST method and data will be parsed as text
const { data } = useFetch(url).post().text()

// Or set the method using the options

// Request will be sent with GET method and data will be parsed as blob
const { data } = useFetch(url, { method: 'GET' }, { refetch: true }).blob()

Creating a Custom Instance

The createFetch function will return a useFetch function with whatever pre-configured options that are provided to it. This is useful for interacting with API's throughout an application that uses the same base URL or needs Authorization headers.

const useMyFetch = createFetch({ 
  baseUrl: 'https://my-api.com', 
  options: {
    async beforeFetch({ options }) {
      const myToken = await getMyToken()
      options.headers.Authorization = `Bearer ${myToken}`

      return { options }
    },
  }, 
  fetchOptions: {
    mode: 'cors',
  },
})

const { isFetching, error, data } = useMyFetch('users')
const useMyFetch = createFetch({ 
  baseUrl: 'https://my-api.com', 
  options: {
    async beforeFetch({ options }) {
      const myToken = await getMyToken()
      options.headers.Authorization = `Bearer ${myToken}`

      return { options }
    },
  }, 
  fetchOptions: {
    mode: 'cors',
  },
})

const { isFetching, error, data } = useMyFetch('users')

Events

The onFetchResponse and onFetchError will fire on fetch request responses and errors respectively.

const { onFetchResponse, onFetchError } = useFetch(url)

onFetchResponse((response) => {
  console.log(response.status)
})

onFetchError((error) => {
  console.error(error.message)
})
const { onFetchResponse, onFetchError } = useFetch(url)

onFetchResponse((response) => {
  console.log(response.status)
})

onFetchError((error) => {
  console.error(error.message)
})

Type Declarations

Show Type Declarations
export interface UseFetchReturn<T> {
  /**
   * Indicates if the fetch request has finished
   */
  isFinished: Ref<boolean>
  /**
   * The statusCode of the HTTP fetch response
   */
  statusCode: Ref<number | null>
  /**
   * The raw response of the fetch response
   */
  response: Ref<Response | null>
  /**
   * Any fetch errors that may have occurred
   */
  error: Ref<any>
  /**
   * The fetch response body, may either be JSON or text
   */
  data: Ref<T | null>
  /**
   * Indicates if the request is currently being fetched.
   */
  isFetching: Ref<boolean>
  /**
   * Indicates if the fetch request is able to be aborted
   */
  canAbort: ComputedRef<boolean>
  /**
   * Indicates if the fetch request was aborted
   */
  aborted: Ref<boolean>
  /**
   * Abort the fetch request
   */
  abort: Fn
  /**
   * Manually call the fetch
   * (default not throwing error)
   */
  execute: (throwOnFailed?: boolean) => Promise<any>
  /**
   * Fires after the fetch request has finished
   */
  onFetchResponse: EventHookOn<Response>
  /**
   * Fires after a fetch request error
   */
  onFetchError: EventHookOn
  /**
   * Fires after a fetch has completed
   */
  onFetchFinally: EventHookOn
  get(): UseFetchReturn<T>
  post(payload?: MaybeRef<unknown>, type?: string): UseFetchReturn<T>
  put(payload?: MaybeRef<unknown>, type?: string): UseFetchReturn<T>
  delete(payload?: MaybeRef<unknown>, type?: string): UseFetchReturn<T>
  patch(payload?: MaybeRef<unknown>, type?: string): UseFetchReturn<T>
  head(payload?: MaybeRef<unknown>, type?: string): UseFetchReturn<T>
  options(payload?: MaybeRef<unknown>, type?: string): UseFetchReturn<T>
  json<JSON = any>(): UseFetchReturn<JSON>
  text(): UseFetchReturn<string>
  blob(): UseFetchReturn<Blob>
  arrayBuffer(): UseFetchReturn<ArrayBuffer>
  formData(): UseFetchReturn<FormData>
}
export interface BeforeFetchContext {
  /**
   * The computed url of the current request
   */
  url: string
  /**
   * The request options of the current request
   */
  options: RequestInit
  /**
   * Cancels the current request
   */
  cancel: Fn
}
export interface AfterFetchContext<T = any> {
  response: Response
  data: T | null
}
export interface OnFetchErrorContext<T = any, E = any> {
  error: E
  data: T | null
}
export interface UseFetchOptions {
  /**
   * Fetch function
   */
  fetch?: typeof window.fetch
  /**
   * Will automatically run fetch when `useFetch` is used
   *
   * @default true
   */
  immediate?: boolean
  /**
   * Will automatically refetch when:
   * - the URL is changed if the URL is a ref
   * - the payload is changed if the payload is a ref
   *
   * @default false
   */
  refetch?: MaybeRef<boolean>
  /**
   * Initial data before the request finished
   *
   * @default null
   */
  initialData?: any
  /**
   * Timeout for abort request after number of millisecond
   * `0` means use browser default
   *
   * @default 0
   */
  timeout?: number
  /**
   * Will run immediately before the fetch request is dispatched
   */
  beforeFetch?: (
    ctx: BeforeFetchContext
  ) =>
    | Promise<Partial<BeforeFetchContext> | void>
    | Partial<BeforeFetchContext>
    | void
  /**
   * Will run immediately after the fetch request is returned.
   * Runs after any 2xx response
   */
  afterFetch?: (
    ctx: AfterFetchContext
  ) => Promise<Partial<AfterFetchContext>> | Partial<AfterFetchContext>
  /**
   * Will run immediately after the fetch request is returned.
   * Runs after any 4xx and 5xx response
   */
  onFetchError?: (
    ctx: OnFetchErrorContext
  ) => Promise<Partial<OnFetchErrorContext>> | Partial<OnFetchErrorContext>
}
export interface CreateFetchOptions {
  /**
   * The base URL that will be prefixed to all urls
   */
  baseUrl?: MaybeRef<string>
  /**
   * Default Options for the useFetch function
   */
  options?: UseFetchOptions
  /**
   * Options for the fetch request
   */
  fetchOptions?: RequestInit
}
export declare function createFetch(
  config?: CreateFetchOptions
): typeof useFetch
export declare function useFetch<T>(
  url: MaybeRef<string>
): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
export declare function useFetch<T>(
  url: MaybeRef<string>,
  useFetchOptions: UseFetchOptions
): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
export declare function useFetch<T>(
  url: MaybeRef<string>,
  options: RequestInit,
  useFetchOptions?: UseFetchOptions
): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
export interface UseFetchReturn<T> {
  /**
   * Indicates if the fetch request has finished
   */
  isFinished: Ref<boolean>
  /**
   * The statusCode of the HTTP fetch response
   */
  statusCode: Ref<number | null>
  /**
   * The raw response of the fetch response
   */
  response: Ref<Response | null>
  /**
   * Any fetch errors that may have occurred
   */
  error: Ref<any>
  /**
   * The fetch response body, may either be JSON or text
   */
  data: Ref<T | null>
  /**
   * Indicates if the request is currently being fetched.
   */
  isFetching: Ref<boolean>
  /**
   * Indicates if the fetch request is able to be aborted
   */
  canAbort: ComputedRef<boolean>
  /**
   * Indicates if the fetch request was aborted
   */
  aborted: Ref<boolean>
  /**
   * Abort the fetch request
   */
  abort: Fn
  /**
   * Manually call the fetch
   * (default not throwing error)
   */
  execute: (throwOnFailed?: boolean) => Promise<any>
  /**
   * Fires after the fetch request has finished
   */
  onFetchResponse: EventHookOn<Response>
  /**
   * Fires after a fetch request error
   */
  onFetchError: EventHookOn
  /**
   * Fires after a fetch has completed
   */
  onFetchFinally: EventHookOn
  get(): UseFetchReturn<T>
  post(payload?: MaybeRef<unknown>, type?: string): UseFetchReturn<T>
  put(payload?: MaybeRef<unknown>, type?: string): UseFetchReturn<T>
  delete(payload?: MaybeRef<unknown>, type?: string): UseFetchReturn<T>
  patch(payload?: MaybeRef<unknown>, type?: string): UseFetchReturn<T>
  head(payload?: MaybeRef<unknown>, type?: string): UseFetchReturn<T>
  options(payload?: MaybeRef<unknown>, type?: string): UseFetchReturn<T>
  json<JSON = any>(): UseFetchReturn<JSON>
  text(): UseFetchReturn<string>
  blob(): UseFetchReturn<Blob>
  arrayBuffer(): UseFetchReturn<ArrayBuffer>
  formData(): UseFetchReturn<FormData>
}
export interface BeforeFetchContext {
  /**
   * The computed url of the current request
   */
  url: string
  /**
   * The request options of the current request
   */
  options: RequestInit
  /**
   * Cancels the current request
   */
  cancel: Fn
}
export interface AfterFetchContext<T = any> {
  response: Response
  data: T | null
}
export interface OnFetchErrorContext<T = any, E = any> {
  error: E
  data: T | null
}
export interface UseFetchOptions {
  /**
   * Fetch function
   */
  fetch?: typeof window.fetch
  /**
   * Will automatically run fetch when `useFetch` is used
   *
   * @default true
   */
  immediate?: boolean
  /**
   * Will automatically refetch when:
   * - the URL is changed if the URL is a ref
   * - the payload is changed if the payload is a ref
   *
   * @default false
   */
  refetch?: MaybeRef<boolean>
  /**
   * Initial data before the request finished
   *
   * @default null
   */
  initialData?: any
  /**
   * Timeout for abort request after number of millisecond
   * `0` means use browser default
   *
   * @default 0
   */
  timeout?: number
  /**
   * Will run immediately before the fetch request is dispatched
   */
  beforeFetch?: (
    ctx: BeforeFetchContext
  ) =>
    | Promise<Partial<BeforeFetchContext> | void>
    | Partial<BeforeFetchContext>
    | void
  /**
   * Will run immediately after the fetch request is returned.
   * Runs after any 2xx response
   */
  afterFetch?: (
    ctx: AfterFetchContext
  ) => Promise<Partial<AfterFetchContext>> | Partial<AfterFetchContext>
  /**
   * Will run immediately after the fetch request is returned.
   * Runs after any 4xx and 5xx response
   */
  onFetchError?: (
    ctx: OnFetchErrorContext
  ) => Promise<Partial<OnFetchErrorContext>> | Partial<OnFetchErrorContext>
}
export interface CreateFetchOptions {
  /**
   * The base URL that will be prefixed to all urls
   */
  baseUrl?: MaybeRef<string>
  /**
   * Default Options for the useFetch function
   */
  options?: UseFetchOptions
  /**
   * Options for the fetch request
   */
  fetchOptions?: RequestInit
}
export declare function createFetch(
  config?: CreateFetchOptions
): typeof useFetch
export declare function useFetch<T>(
  url: MaybeRef<string>
): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
export declare function useFetch<T>(
  url: MaybeRef<string>,
  useFetchOptions: UseFetchOptions
): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
export declare function useFetch<T>(
  url: MaybeRef<string>,
  options: RequestInit,
  useFetchOptions?: UseFetchOptions
): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>

Source

SourceDemoDocs

Contributors

Anthony Fu
wheat
Ismail Gjevori
Jelf
Jay214
webfansplz
unknown_
btea
Shinigami
KaKa
KaKa
Arda Soytürk

Changelog

v7.7.1 on 3/5/2022
53d19 - fix: make error shallow (#1270)
v7.7.0 on 2/26/2022
23b12 - fix: fix run afterFetch condition (#1271)
v7.6.0 on 2/8/2022
01f8d - feat: support more http methods (#1149) (#1193)
v7.4.0 on 12/18/2021
8ee76 - feat: allow useFetch to be awaited (#1056)
v6.9.2 on 11/19/2021
80409 - fix: interface typos (#938)
v6.7.4 on 10/27/2021
868dd - fix: exports useFetch return type
30e69 - feat: timeout (#869)
v6.6.0 on 10/16/2021
905ff - feat: add onFetchError in UseFetchOptions (#841)
v6.3.0 on 9/8/2021
df3ad - feat: add initialData option (#714)
v6.1.0 on 9/2/2021
e5899 - feat: payload supports ref and follow changed (#694)
v5.1.4 on 7/19/2021
50652 - fix(creatFetch): options state immutability, close #629
51a6d - fix: add onFetchFinally. Fix headers issue #625 (#631)
v5.1.3 on 7/7/2021
5bfac - fix: update execute throwing logic
ac729 - fix: reject for execute on error (#612)
v5.1.0 on 7/5/2021
5fbe5 - feat: set content type only if it is json (#573)
ba2b1 - fix: parse body even if status is not ok (#572)
v4.11.1 on 5/24/2021
5b761 - feat(createEventHook): added interface (#531)
v4.11.0 on 5/14/2021
8035c - feat: add afterFetch option, onFetchResponse, and onFetchError (#506)
v4.11.1 on 5/24/2021
7b30a - feat(createEventHook): added interface (#531)
v4.11.0 on 5/14/2021
87a46 - feat: add afterFetch option, onFetchResponse, and onFetchError (#506)
v4.9.3 on 5/11/2021
2d6e3 - fix!: allow setting response type before doing request (#454)
v4.4.0 on 3/13/2021
38677 - fix: SSG issues
v4.3.6 on 3/12/2021
e3c48 - feat: add beforeFetch option (#371)
v4.3.5 on 3/10/2021
2b0e7 - fix: abort controller would only works on first request (#369)
useFetch has loaded