Skip to main content
This composable provides a convenient wrapper around useAsyncData and $fetch. It automatically generates a key based on URL and fetch options, provides type hints for request url based on server routes, and infers API response type.
useFetch is a composable meant to be called directly in a setup function, plugin, or route middleware. It returns reactive composables and handles adding responses to the Nuxt payload so they can be passed from server to client without re-fetching the data on client side when the page hydrates.

Usage

[app/pages/modules.vue]
<script setup lang="ts">
const { data, status, error, refresh, clear } = await useFetch('/api/modules', {
  pick: ['title'],
})
</script>
data, status, and error are Vue refs, and they should be accessed with .value when used within the <script setup>, while refresh/execute and clear are plain functions.

Parameters

url
string | Request | Ref<string | Request> | (() => string | Request)
required
The URL or request to fetch. Can be a string, a Request object, a Vue ref, or a function returning a string/Request. Supports reactivity for dynamic endpoints.
options
UseFetchOptions<T>
Configuration for the fetch request. Extends unjs/ofetch options and AsyncDataOptions. All options can be a static value, a ref, or a computed value.
key
string | Ref<string> | (() => string)
Unique key for de-duplication. If not provided, generated from URL and options.
method
string | Ref<string>
default:"'GET'"
HTTP request method.
query
Record<string, any> | Ref<Record<string, any>>
Query/search params to append to the URL. Objects are automatically stringified. Alias: params.
body
RequestInit['body'] | Record<string, any> | Ref
Request body. Objects are automatically stringified.
headers
Record<string, string> | [key, value][] | Headers | Ref
Request headers.
baseURL
string | Ref<string>
Base URL for the request.
timeout
number | Ref<number>
Timeout in milliseconds to abort the request.
server
boolean
default:"true"
Whether to fetch on the server.
lazy
boolean
default:"false"
If true, resolves after route loads (does not block navigation).
immediate
boolean
default:"true"
If false, prevents request from firing immediately.
default
() => T
Factory for default value of data before async resolves.
transform
(input: T) => T | Promise<T>
Function to transform the result after resolving.
getCachedData
(key: string, nuxtApp: NuxtApp, ctx: AsyncDataRequestContext) => T | undefined
Function to return cached data.
pick
string[]
Only pick specified keys from the result.
watch
WatchSource[] | false
Array of reactive sources to watch and auto-refresh. false disables watching.
deep
boolean
default:"false"
Return data in a deep ref object.
dedupe
'cancel' | 'defer'
default:"'cancel'"
Avoid fetching same key more than once at a time. cancel cancels existing requests. defer does not make new requests if there is a pending one.
$fetch
typeof globalThis.$fetch
Custom $fetch implementation.
onRequest
(ctx: { request, options }) => void
Interceptor called before the request. Can modify options.
onRequestError
(ctx: { request, options, error }) => void
Interceptor called on request errors.
onResponse
(ctx: { request, response, options }) => void
Interceptor called after successful response.
onResponseError
(ctx: { request, response, options }) => void
Interceptor called on response errors.

Return Values

data
Ref<T | undefined>
The result of the asynchronous fetch.
refresh
(opts?: AsyncDataExecuteOptions) => Promise<void>
Function to manually refresh the data. By default, Nuxt waits until a refresh is finished before it can be executed again. Also aliased as execute.
error
Ref<Error | undefined>
Error object if the data fetching failed.
status
Ref<'idle' | 'pending' | 'success' | 'error'>
Status of the data request:
  • idle: Request has not started (e.g. { immediate: false } or { server: false } on server render)
  • pending: Request is in progress
  • success: Request completed successfully
  • error: Request failed
clear
() => void
Resets data to undefined (or the value of options.default() if provided), error to undefined, set status to idle, and cancels any pending requests.

Examples

Query Parameters

Using the query option, you can add search parameters to your query:
const param1 = ref('value1')
const { data, status, error, refresh } = await useFetch('/api/modules', {
  query: { param1, param2: 'value2' },
})

Interceptors

You can use interceptors to handle request and response events:
const { data, status, error, refresh, clear } = await useFetch('/api/auth/login', {
  onRequest ({ request, options }) {
    // Set the request headers
    options.headers.set('Authorization', '...')
  },
  onRequestError ({ request, options, error }) {
    // Handle the request errors
  },
  onResponse ({ request, response, options }) {
    // Process the response data
    localStorage.setItem('token', response._data.token)
  },
  onResponseError ({ request, response, options }) {
    // Handle the response errors
  },
})

Reactive URL

You can use a computed ref or a plain ref as the URL:
[app/pages/[id].vue]
<script setup lang="ts">
const route = useRoute()
const id = computed(() => route.params.id)

const { data: post } = await useFetch(() => `/api/posts/${id.value}`)
</script>

Reactive Fetch Options

Fetch options can be provided as reactive values:
const searchQuery = ref('initial')
const { data } = await useFetch('/api/search', {
  query: { q: searchQuery },
})
// triggers a refetch: /api/search?q=new%20search
searchQuery.value = 'new search'

Type

export function useFetch<DataT, ErrorT> (
  url: string | Request | Ref<string | Request> | (() => string | Request),
  options?: UseFetchOptions<DataT>,
): Promise<AsyncData<DataT, ErrorT>>

type UseFetchOptions<DataT> = {
  key?: MaybeRefOrGetter<string>
  method?: MaybeRefOrGetter<string>
  query?: MaybeRefOrGetter<SearchParams>
  params?: MaybeRefOrGetter<SearchParams>
  body?: MaybeRefOrGetter<RequestInit['body'] | Record<string, any>>
  headers?: MaybeRefOrGetter<Record<string, string> | [key: string, value: string][] | Headers>
  baseURL?: MaybeRefOrGetter<string>
  server?: boolean
  lazy?: boolean
  immediate?: boolean
  getCachedData?: (key: string, nuxtApp: NuxtApp, ctx: AsyncDataRequestContext) => DataT | undefined
  deep?: boolean
  dedupe?: 'cancel' | 'defer'
  timeout?: number
  default?: () => DataT
  transform?: (input: DataT) => DataT | Promise<DataT>
  pick?: string[]
  $fetch?: typeof globalThis.$fetch
  watch?: MultiWatchSources | false
}