Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Apply VueUse composables in Vue 3/Nuxt projects to replace custom implementations with battle-tested utilities.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/useFetch.md
1---2category: Network3---45# useFetch67Reactive [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) provides the ability to abort requests, intercept requests before8they are fired, automatically refetch requests when the url changes, and create your own `useFetch` with predefined options.910<CourseLink href="https://vueschool.io/lessons/vueuse-utilities-usefetch-and-reactify?friend=vueuse">Learn useFetch with this FREE video lesson from Vue School!</CourseLink>1112::: tip13When 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.14:::1516## Usage1718### Basic Usage1920The `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.2122```ts23import { useFetch } from '@vueuse/core'2425const { isFetching, error, data } = useFetch(url)26```2728### Asynchronous Usage2930`useFetch` can also be awaited just like a normal fetch. Note that whenever a component is asynchronous, whatever component that uses31it must wrap the component in a `<Suspense>` tag. You can read more about the suspense api in the [Official Vue 3 Docs](https://vuejs.org/guide/built-ins/suspense.html)3233```ts34import { useFetch } from '@vueuse/core'35// ---cut---36const { isFetching, error, data } = await useFetch(url)37```3839### Refetching on URL change4041Using a `ref` for the url parameter will allow the `useFetch` function to automatically trigger another request when the url is changed.4243```ts44import { useFetch } from '@vueuse/core'45// ---cut---46const url = ref('https://my-api.com/user/1')4748const { data } = useFetch(url, { refetch: true })4950url.value = 'https://my-api.com/user/2' // Will trigger another request51```5253### Prevent request from firing immediately5455Setting the `immediate` option to false will prevent the request from firing until the `execute` function is called.5657```ts58import { useFetch } from '@vueuse/core'59// ---cut---60const { execute } = useFetch(url, { immediate: false })6162execute()63```6465### Aborting a request6667A request can be aborted by using the `abort` function from the `useFetch` function. The `canAbort` property indicates if the request can be aborted.6869```ts70import { useFetch } from '@vueuse/core'71// ---cut---72const { abort, canAbort } = useFetch(url)7374setTimeout(() => {75if (canAbort.value)76abort()77}, 100)78```7980A request can also be aborted automatically by using `timeout` property. It will call `abort` function when the given timeout is reached.8182```ts83import { useFetch } from '@vueuse/core'84// ---cut---85const { data } = useFetch(url, { timeout: 100 })86```8788### Intercepting a request8990The `beforeFetch` option can intercept a request before it is sent and modify the request options and url.9192```ts93import { useFetch } from '@vueuse/core'94// ---cut---95const { data } = useFetch(url, {96async beforeFetch({ url, options, cancel }) {97const myToken = await getMyToken()9899if (!myToken)100cancel()101102options.headers = {103...options.headers,104Authorization: `Bearer ${myToken}`,105}106107return {108options,109}110},111})112```113114The `afterFetch` option can intercept the response data before it is updated.115116```ts117import { useFetch } from '@vueuse/core'118// ---cut---119const { data } = useFetch(url, {120afterFetch(ctx) {121if (ctx.data.title === 'HxH')122ctx.data.title = 'Hunter x Hunter' // Modifies the response data123124return ctx125},126})127```128129The `onFetchError` option can intercept the response data and error before it is updated when `updateDataOnError` is set to `true`.130131```ts132import { useFetch } from '@vueuse/core'133// ---cut---134const { data } = useFetch(url, {135updateDataOnError: true,136onFetchError(ctx) {137// ctx.data can be null when 5xx response138if (ctx.data === null)139ctx.data = { title: 'Hunter x Hunter' } // Modifies the response data140141ctx.error = new Error('Custom Error') // Modifies the error142return ctx143},144})145146console.log(data.value) // { title: 'Hunter x Hunter' }147```148149### Setting the request method and return type150151The request method and return type can be set by adding the appropriate methods to the end of `useFetch`152153```ts154import { useFetch } from '@vueuse/core'155// ---cut---156// Request will be sent with GET method and data will be parsed as JSON157const { data } = useFetch(url).get().json()158159// Request will be sent with POST method and data will be parsed as text160const { data } = useFetch(url).post().text()161162// Or set the method using the options163164// Request will be sent with GET method and data will be parsed as blob165const { data } = useFetch(url, { method: 'GET' }, { refetch: true }).blob()166```167168### Creating a Custom Instance169170The `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.171172```ts173import { createFetch } from '@vueuse/core'174// ---cut---175const useMyFetch = createFetch({176baseUrl: 'https://my-api.com',177options: {178async beforeFetch({ options }) {179const myToken = await getMyToken()180options.headers.Authorization = `Bearer ${myToken}`181182return { options }183},184},185fetchOptions: {186mode: 'cors',187},188})189190const { isFetching, error, data } = useMyFetch('users')191```192193If 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`.194195```ts196import { createFetch } from '@vueuse/core'197// ---cut---198const useMyFetch = createFetch({199baseUrl: 'https://my-api.com',200combination: 'overwrite',201options: {202// beforeFetch in pre-configured instance will only run when the newly spawned instance do not pass beforeFetch203async beforeFetch({ options }) {204const myToken = await getMyToken()205options.headers.Authorization = `Bearer ${myToken}`206207return { options }208},209},210})211212// use useMyFetch beforeFetch213const { isFetching, error, data } = useMyFetch('users')214215// use custom beforeFetch216const { isFetching, error, data } = useMyFetch('users', {217async beforeFetch({ url, options, cancel }) {218const myToken = await getMyToken()219220if (!myToken)221cancel()222223options.headers = {224...options.headers,225Authorization: `Bearer ${myToken}`,226}227228return {229options,230}231},232})233```234235You can re-execute the request by calling the `execute` method in `afterFetch` or `onFetchError`. Here is a simple example of refreshing a token:236237```ts238import { createFetch } from '@vueuse/core'239// ---cut---240let isRefreshing = false241const refreshSubscribers: Array<() => void> = []242243const useMyFetch = createFetch({244baseUrl: 'https://my-api.com',245options: {246async beforeFetch({ options }) {247const myToken = await getMyToken()248options.headers.Authorization = `Bearer ${myToken}`249250return { options }251},252afterFetch({ data, response, context, execute }) {253if (needRefreshToken) {254if (!isRefreshing) {255isRefreshing = true256refreshToken().then((newToken) => {257if (newToken.value) {258isRefreshing = false259setMyToken(newToken.value)260onRefreshed()261}262else {263refreshSubscribers.length = 0264// handle refresh token error265}266})267}268269return new Promise((resolve) => {270addRefreshSubscriber(() => {271execute().then((response) => {272resolve({ data, response })273})274})275})276}277278return { data, response }279},280// or use onFetchError with updateDataOnError281updateDataOnError: true,282onFetchError({ error, data, response, context, execute }) {283// same as afterFetch284return { error, data }285},286},287fetchOptions: {288mode: 'cors',289},290})291292async function refreshToken() {293const { data, execute } = useFetch<string>('refresh-token', {294immediate: false,295})296297await execute()298return data299}300301function onRefreshed() {302refreshSubscribers.forEach(callback => callback())303refreshSubscribers.length = 0304}305306function addRefreshSubscriber(callback: () => void) {307refreshSubscribers.push(callback)308}309310const { isFetching, error, data } = useMyFetch('users')311```312313### Events314315The `onFetchResponse` and `onFetchError` will fire on fetch request responses and errors respectively.316317```ts318import { useFetch } from '@vueuse/core'319// ---cut---320const { onFetchResponse, onFetchError } = useFetch(url)321322onFetchResponse((response) => {323console.log(response.status)324})325326onFetchError((error) => {327console.error(error.message)328})329```330331## Type Declarations332333```ts334export interface UseFetchReturn<T> {335/**336* Indicates if the fetch request has finished337*/338isFinished: Readonly<ShallowRef<boolean>>339/**340* The statusCode of the HTTP fetch response341*/342statusCode: ShallowRef<number | null>343/**344* The raw response of the fetch response345*/346response: ShallowRef<Response | null>347/**348* Any fetch errors that may have occurred349*/350error: ShallowRef<any>351/**352* The fetch response body on success, may either be JSON or text353*/354data: ShallowRef<T | null>355/**356* Indicates if the request is currently being fetched.357*/358isFetching: Readonly<ShallowRef<boolean>>359/**360* Indicates if the fetch request is able to be aborted361*/362canAbort: ComputedRef<boolean>363/**364* Indicates if the fetch request was aborted365*/366aborted: ShallowRef<boolean>367/**368* Abort the fetch request369*/370abort: (reason?: any) => void371/**372* Manually call the fetch373* (default not throwing error)374*/375execute: (throwOnFailed?: boolean) => Promise<any>376/**377* Fires after the fetch request has finished378*/379onFetchResponse: EventHookOn<Response>380/**381* Fires after a fetch request error382*/383onFetchError: EventHookOn384/**385* Fires after a fetch has completed386*/387onFetchFinally: EventHookOn388get: () => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>389post: (390payload?: MaybeRefOrGetter<unknown>,391type?: string,392) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>393put: (394payload?: MaybeRefOrGetter<unknown>,395type?: string,396) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>397delete: (398payload?: MaybeRefOrGetter<unknown>,399type?: string,400) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>401patch: (402payload?: MaybeRefOrGetter<unknown>,403type?: string,404) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>405head: (406payload?: MaybeRefOrGetter<unknown>,407type?: string,408) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>409options: (410payload?: MaybeRefOrGetter<unknown>,411type?: string,412) => UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>413json: <JSON = any>() => UseFetchReturn<JSON> &414PromiseLike<UseFetchReturn<JSON>>415text: () => UseFetchReturn<string> & PromiseLike<UseFetchReturn<string>>416blob: () => UseFetchReturn<Blob> & PromiseLike<UseFetchReturn<Blob>>417arrayBuffer: () => UseFetchReturn<ArrayBuffer> &418PromiseLike<UseFetchReturn<ArrayBuffer>>419formData: () => UseFetchReturn<FormData> &420PromiseLike<UseFetchReturn<FormData>>421}422type Combination = "overwrite" | "chain"423export interface BeforeFetchContext {424/**425* The computed url of the current request426*/427url: string428/**429* The request options of the current request430*/431options: RequestInit432/**433* Cancels the current request434*/435cancel: Fn436}437export interface AfterFetchContext<T = any> {438response: Response439data: T | null440context: BeforeFetchContext441execute: (throwOnFailed?: boolean) => Promise<any>442}443export interface OnFetchErrorContext<T = any, E = any> {444error: E445data: T | null446response: Response | null447context: BeforeFetchContext448execute: (throwOnFailed?: boolean) => Promise<any>449}450export interface UseFetchOptions {451/**452* Fetch function453*/454fetch?: typeof window.fetch455/**456* Will automatically run fetch when `useFetch` is used457*458* @default true459*/460immediate?: boolean461/**462* Will automatically refetch when:463* - the URL is changed if the URL is a ref464* - the payload is changed if the payload is a ref465*466* @default false467*/468refetch?: MaybeRefOrGetter<boolean>469/**470* Initial data before the request finished471*472* @default null473*/474initialData?: any475/**476* Timeout for abort request after number of millisecond477* `0` means use browser default478*479* @default 0480*/481timeout?: number482/**483* Allow update the `data` ref when fetch error whenever provided, or mutated in the `onFetchError` callback484*485* @default false486*/487updateDataOnError?: boolean488/**489* Will run immediately before the fetch request is dispatched490*/491beforeFetch?: (492ctx: BeforeFetchContext,493) =>494| Promise<Partial<BeforeFetchContext> | void>495| Partial<BeforeFetchContext>496| void497/**498* Will run immediately after the fetch request is returned.499* Runs after any 2xx response500*/501afterFetch?: (502ctx: AfterFetchContext,503) => Promise<Partial<AfterFetchContext>> | Partial<AfterFetchContext>504/**505* Will run immediately after the fetch request is returned.506* Runs after any 4xx and 5xx response507*/508onFetchError?: (509ctx: OnFetchErrorContext,510) => Promise<Partial<OnFetchErrorContext>> | Partial<OnFetchErrorContext>511}512export interface CreateFetchOptions {513/**514* The base URL that will be prefixed to all urls unless urls are absolute515*/516baseUrl?: MaybeRefOrGetter<string>517/**518* Determine the inherit behavior for beforeFetch, afterFetch, onFetchError519* @default 'chain'520*/521combination?: Combination522/**523* Default Options for the useFetch function524*/525options?: UseFetchOptions526/**527* Options for the fetch request528*/529fetchOptions?: RequestInit530}531export declare function createFetch(532config?: CreateFetchOptions,533): typeof useFetch534export declare function useFetch<T>(535url: MaybeRefOrGetter<string>,536): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>537export declare function useFetch<T>(538url: MaybeRefOrGetter<string>,539useFetchOptions: UseFetchOptions,540): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>541export declare function useFetch<T>(542url: MaybeRefOrGetter<string>,543options: RequestInit,544useFetchOptions?: UseFetchOptions,545): UseFetchReturn<T> & PromiseLike<UseFetchReturn<T>>546```547