useFetch
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 useFetch
with predefined options.
TIP
When using with Nuxt 3, this function will NOT be auto imported in favor of Nuxt's built-in useFetch()
. Use explicit import if you want to use the function from VueUse.
Demo
https://httpbin.org/get
https://httpbin.org/delay/10
http://httpbin.org/status/500
isFinished: false isFetching: false canAbort: false statusCode: null error: null data: null
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.
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 <Suspense>
tag. You can read more about the suspense api in the Official Vue 3 Docs
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 useFetch
function 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
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()
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.
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 })
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,
}
},
})
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
},
})
The onFetchError
option can intercept the response data and error before it is updated when updateDataOnError
is set to true
.
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
// 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')
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
.
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,
}
},
})
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)
})
Type Declarations
Show Type Declarations
export interface UseFetchReturn<T> {
/**
* Indicates if the fetch request has finished
*/
isFinished: Readonly<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 on success, may either be JSON or text
*/
data: Ref<T | null>
/**
* Indicates if the request is currently being fetched.
*/
isFetching: Readonly<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> & PromiseLike<UseFetchReturn<T>>
post: (
payload?: MaybeRefOrGetter<unknown>,
type?: string,
) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
put: (
payload?: MaybeRefOrGetter<unknown>,
type?: string,
) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
delete: (
payload?: MaybeRefOrGetter<unknown>,
type?: string,
) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
patch: (
payload?: MaybeRefOrGetter<unknown>,
type?: string,
) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
head: (
payload?: MaybeRefOrGetter<unknown>,
type?: string,
) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
options: (
payload?: MaybeRefOrGetter<unknown>,
type?: string,
) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
json: <JSON = any>() => UseFetchReturn<JSON> &
PromiseLike<UseFetchReturn<JSON>>
text: () => UseFetchReturn<string> & PromiseLike<UseFetchReturn<string>>
blob: () => UseFetchReturn<Blob> & PromiseLike<UseFetchReturn<Blob>>
arrayBuffer: () => UseFetchReturn<ArrayBuffer> &
PromiseLike<UseFetchReturn<ArrayBuffer>>
formData: () => UseFetchReturn<FormData> &
PromiseLike<UseFetchReturn<FormData>>
}
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<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?: MaybeRefOrGetter<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
/**
* 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<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: {
data: any
response: Response | null
error: any
}) => Promise<Partial<OnFetchErrorContext>> | Partial<OnFetchErrorContext>
}
export interface CreateFetchOptions {
/**
* The base URL that will be prefixed to all urls unless urls are absolute
*/
baseUrl?: MaybeRefOrGetter<string>
/**
* 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<T>(
url: MaybeRefOrGetter<string>,
): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
export declare function useFetch<T>(
url: MaybeRefOrGetter<string>,
useFetchOptions: UseFetchOptions,
): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
export declare function useFetch<T>(
url: MaybeRefOrGetter<string>,
options: RequestInit,
useFetchOptions?: UseFetchOptions,
): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>
Source
Contributors
Changelog
v10.8.0
on 2/20/2024a086e
- fix: stricter typesv10.7.0
on 12/5/2023v10.6.0
on 11/9/2023v10.4.0
on 8/25/2023v10.3.0
on 7/30/2023v10.1.1
on 5/1/2023v10.0.0-beta.4
on 4/13/20234d757
- feat(types)!: rename MaybeComputedRef
to MaybeRefOrGetter
10e98
- feat(toRef)!: rename resolveRef
to toRef
0a72b
- feat(toValue): rename resolveUnref
to toValue
v10.0.0-beta.0
on 3/14/2023v9.13.0
on 2/18/2023c2bc6
- fix: check if it's object for isFetchOptions
v9.9.0
on 12/23/2022v9.5.0
on 11/9/2022v9.3.1
on 10/17/2022