---
category: Network
---
# useFetch
Reactive [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/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 `useFetch` with predefined options.
Learn useFetch with this FREE video lesson from Vue School!
::: tip
When using with Nuxt 3, this function will **NOT** be auto imported in favor of Nuxt's built-in [`useFetch()`](https://v3.nuxtjs.org/api/composables/use-fetch). Use explicit import if you want to use the function from VueUse.
:::
## Usage
### Basic Usage
The `useFetch` function 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.
```ts
import { useFetch } from '@vueuse/core'
const { isFetching, error, data } = useFetch(url)
```
### Asynchronous Usage
`useFetch` can 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 `` tag. You can read more about the suspense api in the [Official Vue 3 Docs](https://vuejs.org/guide/built-ins/suspense.html)
```ts
import { useFetch } from '@vueuse/core'
// ---cut---
const { isFetching, error, data } = await useFetch(url)
```
### Refetching on URL change
Using a `ref` for the url parameter will allow the `useFetch` function to automatically trigger another request when the url is changed.
```ts
import { useFetch } from '@vueuse/core'
// ---cut---
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.
```ts
import { useFetch } from '@vueuse/core'
// ---cut---
const { execute } = useFetch(url, { immediate: false })
execute()
```
### Aborting a request
A request can be aborted by using the `abort` function from the `useFetch` function. The `canAbort` property indicates if the request can be aborted.
```ts
import { useFetch } from '@vueuse/core'
// ---cut---
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.
```ts
import { useFetch } from '@vueuse/core'
// ---cut---
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.
```ts
import { useFetch } from '@vueuse/core'
// ---cut---
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.
```ts
import { useFetch } from '@vueuse/core'
// ---cut---
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 when `updateDataOnError` is set to `true`.
```ts
import { useFetch } from '@vueuse/core'
// ---cut---
const { data } = useFetch(url, {
updateDataOnError: true,
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
},
})
console.log(data.value) // { title: 'Hunter x Hunter' }
```
### 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`
```ts
import { useFetch } from '@vueuse/core'
// ---cut---
// 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.
```ts
import { createFetch } from '@vueuse/core'
// ---cut---
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')
```
If you want to control the behavior of `beforeFetch`, `afterFetch`, `onFetchError` between the pre-configured instance and newly spawned instance. You can provide a `combination` option to toggle between `overwrite` or `chaining`.
```ts
import { createFetch } from '@vueuse/core'
// ---cut---
const useMyFetch = createFetch({
baseUrl: 'https://my-api.com',
combination: 'overwrite',
options: {
// beforeFetch in pre-configured instance will only run when the newly spawned instance do not pass beforeFetch
async beforeFetch({ options }) {
const myToken = await getMyToken()
options.headers.Authorization = `Bearer ${myToken}`
return { options }
},
},
})
// use useMyFetch beforeFetch
const { isFetching, error, data } = useMyFetch('users')
// use custom beforeFetch
const { isFetching, error, data } = useMyFetch('users', {
async beforeFetch({ url, options, cancel }) {
const myToken = await getMyToken()
if (!myToken)
cancel()
options.headers = {
...options.headers,
Authorization: `Bearer ${myToken}`,
}
return {
options,
}
},
})
```
You can re-execute the request by calling the `execute` method in `afterFetch` or `onFetchError`. Here is a simple example of refreshing a token:
```ts
import { createFetch } from '@vueuse/core'
// ---cut---
let isRefreshing = false
const refreshSubscribers: Array<() => void> = []
const useMyFetch = createFetch({
baseUrl: 'https://my-api.com',
options: {
async beforeFetch({ options }) {
const myToken = await getMyToken()
options.headers.Authorization = `Bearer ${myToken}`
return { options }
},
afterFetch({ data, response, context, execute }) {
if (needRefreshToken) {
if (!isRefreshing) {
isRefreshing = true
refreshToken().then((newToken) => {
if (newToken.value) {
isRefreshing = false
setMyToken(newToken.value)
onRefreshed()
}
else {
refreshSubscribers.length = 0
// handle refresh token error
}
})
}
return new Promise((resolve) => {
addRefreshSubscriber(() => {
execute().then((response) => {
resolve({ data, response })
})
})
})
}
return { data, response }
},
// or use onFetchError with updateDataOnError
updateDataOnError: true,
onFetchError({ error, data, response, context, execute }) {
// same as afterFetch
return { error, data }
},
},
fetchOptions: {
mode: 'cors',
},
})
async function refreshToken() {
const { data, execute } = useFetch('refresh-token', {
immediate: false,
})
await execute()
return data
}
function onRefreshed() {
refreshSubscribers.forEach(callback => callback())
refreshSubscribers.length = 0
}
function addRefreshSubscriber(callback: () => void) {
refreshSubscribers.push(callback)
}
const { isFetching, error, data } = useMyFetch('users')
```
### Events
The `onFetchResponse` and `onFetchError` will fire on fetch request responses and errors respectively.
```ts
import { useFetch } from '@vueuse/core'
// ---cut---
const { onFetchResponse, onFetchError } = useFetch(url)
onFetchResponse((response) => {
console.log(response.status)
})
onFetchError((error) => {
console.error(error.message)
})
```
## Type Declarations
```ts
export interface UseFetchReturn {
/**
* Indicates if the fetch request has finished
*/
isFinished: Readonly>
/**
* The statusCode of the HTTP fetch response
*/
statusCode: ShallowRef
/**
* The raw response of the fetch response
*/
response: ShallowRef
/**
* Any fetch errors that may have occurred
*/
error: ShallowRef
/**
* The fetch response body on success, may either be JSON or text
*/
data: ShallowRef
/**
* Indicates if the request is currently being fetched.
*/
isFetching: Readonly>
/**
* Indicates if the fetch request is able to be aborted
*/
canAbort: ComputedRef
/**
* Indicates if the fetch request was aborted
*/
aborted: ShallowRef
/**
* Abort the fetch request
*/
abort: (reason?: any) => void
/**
* Manually call the fetch
* (default not throwing error)
*/
execute: (throwOnFailed?: boolean) => Promise
/**
* Fires after the fetch request has finished
*/
onFetchResponse: EventHookOn
/**
* Fires after a fetch request error
*/
onFetchError: EventHookOn
/**
* Fires after a fetch has completed
*/
onFetchFinally: EventHookOn
get: () => UseFetchReturn & PromiseLike>
post: (
payload?: MaybeRefOrGetter,
type?: string,
) => UseFetchReturn & PromiseLike>
put: (
payload?: MaybeRefOrGetter,
type?: string,
) => UseFetchReturn & PromiseLike>
delete: (
payload?: MaybeRefOrGetter,
type?: string,
) => UseFetchReturn & PromiseLike>
patch: (
payload?: MaybeRefOrGetter,
type?: string,
) => UseFetchReturn & PromiseLike>
head: (
payload?: MaybeRefOrGetter,
type?: string,
) => UseFetchReturn & PromiseLike>
options: (
payload?: MaybeRefOrGetter,
type?: string,
) => UseFetchReturn & PromiseLike>
json: () => UseFetchReturn &
PromiseLike>
text: () => UseFetchReturn & PromiseLike>
blob: () => UseFetchReturn & PromiseLike>
arrayBuffer: () => UseFetchReturn &
PromiseLike>
formData: () => UseFetchReturn &
PromiseLike>
}
type Combination = "overwrite" | "chain"
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 {
response: Response
data: T | null
context: BeforeFetchContext
execute: (throwOnFailed?: boolean) => Promise
}
export interface OnFetchErrorContext {
error: E
data: T | null
response: Response | null
context: BeforeFetchContext
execute: (throwOnFailed?: boolean) => Promise
}
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?: MaybeRefOrGetter
/**
* 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
/**
* Allow update the `data` ref when fetch error whenever provided, or mutated in the `onFetchError` callback
*
* @default false
*/
updateDataOnError?: boolean
/**
* Will run immediately before the fetch request is dispatched
*/
beforeFetch?: (
ctx: BeforeFetchContext,
) =>
| Promise | void>
| Partial
| void
/**
* Will run immediately after the fetch request is returned.
* Runs after any 2xx response
*/
afterFetch?: (
ctx: AfterFetchContext,
) => Promise> | Partial
/**
* Will run immediately after the fetch request is returned.
* Runs after any 4xx and 5xx response
*/
onFetchError?: (
ctx: OnFetchErrorContext,
) => Promise> | Partial
}
export interface CreateFetchOptions {
/**
* The base URL that will be prefixed to all urls unless urls are absolute
*/
baseUrl?: MaybeRefOrGetter
/**
* Determine the inherit behavior for beforeFetch, afterFetch, onFetchError
* @default 'chain'
*/
combination?: Combination
/**
* 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(
url: MaybeRefOrGetter,
): UseFetchReturn & PromiseLike>
export declare function useFetch(
url: MaybeRefOrGetter,
useFetchOptions: UseFetchOptions,
): UseFetchReturn & PromiseLike>
export declare function useFetch(
url: MaybeRefOrGetter,
options: RequestInit,
useFetchOptions?: UseFetchOptions,
): UseFetchReturn & PromiseLike>
```