Within your pages, components, and plugins you can use useAsyncData to get access to data that resolves asynchronously.
useAsyncData is a composable meant to be called directly in the Nuxt context. 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.<script setup lang="ts">
const { data, status, error, refresh, clear } = await useAsyncData(
'mountains',
() => $fetch('https://api.nuxtjs.dev/mountains'),
)
</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.The built-in watch option allows automatically rerunning the fetcher function when any changes are detected.
<script setup lang="ts">
const page = ref(1)
const { data: posts } = await useAsyncData(
'posts',
() => $fetch('https://fakeApi.com/posts', {
params: {
page: page.value,
},
}), {
watch: [page],
},
)
</script>
You can use a computed ref, plain ref or a getter function as the key, allowing for dynamic data fetching that automatically updates when the key changes:
<script setup lang="ts">
const route = useRoute()
const userId = computed(() => `user-${route.params.id}`)
// When the route changes and userId updates, the data will be automatically refetched
const { data: user } = useAsyncData(
userId,
() => fetchUserById(route.params.id),
)
</script>
useAsyncData is a reserved function name transformed by the compiler, so you should not name your own function useAsyncData.key: a unique key to ensure that data fetching can be properly de-duplicated across requests. If you do not provide a key, then a key that is unique to the file name and line number of the instance of useAsyncData will be generated for you.handler: an asynchronous function that must return a truthy value (for example, it should not be undefined or null) or the request may be duplicated on the client side.
handler function should be side-effect free to ensure predictable behavior during SSR and CSR hydration. If you need to trigger side effects, use the callOnce utility to do so.options:
server: whether to fetch the data on the server (defaults to true)lazy: whether to resolve the async function after loading the route, instead of blocking client-side navigation (defaults to false)immediate: when set to false, will prevent the request from firing immediately. (defaults to true)default: a factory function to set the default value of the data, before the async function resolves - useful with the lazy: true or immediate: false optiontransform: a function that can be used to alter handler function result after resolvinggetCachedData: Provide a function which returns cached data. A null or undefined return value will trigger a fetch. By default, this is:
const getDefaultCachedData = (key, nuxtApp, ctx) => nuxtApp.isHydrating
? nuxtApp.payload.data[key]
: nuxtApp.static.data[key]
experimental.payloadExtraction of nuxt.config is enabled.pick: only pick specified keys in this array from the handler function resultwatch: watch reactive sources to auto-refreshdeep: return data in a deep ref object (it is true by default). It can be set to false to return data in a shallow ref object, which can improve performance if your data does not need to be deeply reactive.dedupe: avoid fetching same key more than once at a time (defaults to cancel). Possible options:
cancel - cancels existing requests when a new one is madedefer - does not make new requests at all if there is a pending requesttimeout - a number in milliseconds to wait before timing out the request (defaults to undefined, which means no timeout)lazy: false uses <Suspense> to block the loading of the route before the data has been fetched. Consider using lazy: true and implementing a loading state instead for a snappier user experience.When using the same key for multiple useAsyncData calls, they will share the same data, error and status refs. This ensures consistency across components but requires option consistency.
The following options must be consistent across all calls with the same key:
handler functiondeep optiontransform functionpick arraygetCachedData functiondefault valueThe following options can differ without triggering warnings:
serverlazyimmediatededupewatch// ❌ This will trigger a development warning
const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { deep: false })
const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { deep: true })
// ✅ This is allowed
const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: true })
const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: false })
useAsyncData can be retrieved across your Nuxt application using useNuxtData.data: the result of the asynchronous function that is passed in.refresh/execute: a function that can be used to refresh the data returned by the handler function.error: an error object if the data fetching failed.status: a string indicating the status of the data request:
idle: when the request has not started, such as:
execute has not yet been called and { immediate: false } is set{ server: false } is setpending: the request is in progresssuccess: the request has completed successfullyerror: the request has failedclear: a function that can be used to set data to undefined (or the value of options.default() if provided), set error to null, set status to idle, and mark any currently pending requests as cancelled.By default, Nuxt waits until a refresh is finished before it can be executed again.
server: false), then the data will not be fetched until hydration completes. This means even if you await useAsyncData on the client side, data will remain undefined within <script setup>.export function useAsyncData<DataT, DataE> (
handler: (nuxtApp: NuxtApp, options: { signal: AbortSignal }) => Promise<DataT>,
options?: AsyncDataOptions<DataT>
): AsyncData<DataT, DataE>
export function useAsyncData<DataT, DataE> (
key: MaybeRefOrGetter<string>,
handler: (nuxtApp: NuxtApp, options: { signal: AbortSignal }) => Promise<DataT>,
options?: AsyncDataOptions<DataT>
): Promise<AsyncData<DataT, DataE>>
type AsyncDataOptions<DataT> = {
server?: boolean
lazy?: boolean
immediate?: boolean
deep?: boolean
dedupe?: 'cancel' | 'defer'
default?: () => DataT | Ref<DataT> | null
transform?: (input: DataT) => DataT | Promise<DataT>
pick?: string[]
watch?: MultiWatchSources | false
getCachedData?: (key: string, nuxtApp: NuxtApp, ctx: AsyncDataRequestContext) => DataT | undefined
timeout?: number
}
type AsyncDataRequestContext = {
/** The reason for this data request */
cause: 'initial' | 'refresh:manual' | 'refresh:hook' | 'watch'
}
type AsyncData<DataT, ErrorT> = {
data: Ref<DataT | null>
refresh: (opts?: AsyncDataExecuteOptions) => Promise<void>
execute: (opts?: AsyncDataExecuteOptions) => Promise<void>
clear: () => void
error: Ref<ErrorT | null>
status: Ref<AsyncDataRequestStatus>
}
interface AsyncDataExecuteOptions {
dedupe?: 'cancel' | 'defer'
timeout?: number
signal?: AbortSignal
}
type AsyncDataRequestStatus = 'idle' | 'pending' | 'success' | 'error'