Skip to content

useFetch

Category
Export Size
2.42 kB
Last Changed
last month

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.

Learn useFetch with this FREE video lesson from Vue School!

TIP

When using with Nuxt 3, this functions 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

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 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)
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 Offical Vue 3 Docs

ts
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 useFetch function to automatically trigger another request when the url is changed.

ts
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.

ts
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 useFetch function. The canAbort property indicates if the request can be aborted.

ts
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.

ts
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.

ts
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.

ts
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 when updateDataOnError is set to true.

ts
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' }
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
// 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.

ts
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')

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
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,
    }
  },
})
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.

ts
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)
})

Source

SourceDemoDocs

Contributors

Anthony Fu
wheat
Jelf
Ismail Gjevori
丶远方
KaKa
Toby Zerner
Jay214
webfansplz
KaKa
qiang
RAX7
Przemek Brzosko
abitwhy
sun0day
Young
sun0day
Curt Grimes
Yvan Zhu
ice
Antonio Román
Glandos
unknown_
btea
Shinigami
KaKa
Arda Soytürk

Changelog

v10.4.0 on 8/25/2023
945ca - feat: introduce updateDataOnError option (#3092)
v10.3.0 on 7/30/2023
b7e3d - fix: generated payloadType on execute (#3251)
v10.1.1 on 5/1/2023
d051f - fix: combineCallbacks does not merge options (#3015)
v10.0.0-beta.4 on 4/13/2023
4d757 - 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/2023
78cfb - feat: update data on success (#2711)
fff45 - fix: abort before updating state (#2805)
v9.13.0 on 2/18/2023
cd9d6 - feat: cancel previous request on refetch (#2750)
c2bc6 - fix: check if it's object for isFetchOptions
v9.9.0 on 12/23/2022
000fd - fix: doesn't work with formData payload (#2440)
v9.5.0 on 11/9/2022
934a8 - feat: support sending the custom request to an absolute URL regardless baseURL (#2210)
a8496 - feat: allow configure lifecycle handler behavior (#2333)
v9.3.1 on 10/17/2022
45750 - fix: fix incorrect chainCallbacks behavior (#2231)
v9.0.1 on 7/29/2022
0f791 - fix: broken callbacks when RequestInit and UseFetchOptions are both passed in (#2013)
v8.9.1 on 7/8/2022
a9ccc - feat(all): use MaybeComputedRef (#1768)
v8.9.0 on 7/6/2022
08830 - feat: chain callbacks from createFetch and useFetch (#1545)
v8.7.0 on 6/16/2022
8f541 - fix: ssr compactible for headersToObject
v8.5.0 on 5/16/2022
9b286 - fix: return PromiseLike after setting method (#1571)
56eb3 - fix: respect custom fetch option (#1603)

Released under the MIT License.