Invalid useAsyncData pending state if data is cached

I have a custom wrapper around data fetching like this: export const useApiData = <T = unknown, R = T>( key: string, endpoint: string | Ref<string> | ComputedRef<string>, options: Omit<AsyncDataOptions<ApiResponse<T>, R>, 'transform'> & { query?: Record<string, any>; method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; body?: any; transform?: (data: ApiResponse<T>) => R; onResponse?: (context: { request: any; response: any; options: any; }) => void | Promise<void>; onResponseError?: (context: { request: any; response: any; options: any; }) => void | Promise<void>; } = {}, ) => { ... // ommitted const api = useStandardizedApi(); return useAsyncData<ApiResponse<T>, StandardErrorResponse, R>( key, () => api.handleApiCall<T>(unref(endpoint), { method, query, body, onResponse, onResponseError, }), { ...asyncDataOptions, transform: transform as AsyncDataOptions<ApiResponse<T>, R>['transform'], }, ); }; A sample usage is like this const { pending: fetchingClientVehicles, error: errorFetchingClientVehicles, execute: refetchClientVehicles, data: clientVehicles, } = useApiData<TrackedVehicles[], TrackedVehicles[]>('client-devices', computedURL, { method: 'GET', server: false, immediate: false, ... // code ommitted });. Because of the key, the data is cached as expected. However, the value of fetchingClient vehicles still remains true even though I can see the data on the screen. Any pointers as to why this could be happening?
2 Replies
kapa.ai
kapa.ai2mo ago
Hi @OffWhiteOrBlack. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- The behavior you're seeing—where the pending state remains true even though data is already present—relates to a recent change in how Nuxt handles the pending property in useAsyncData and useFetch. Key points from the documentation: - As of Nuxt 3 and 4, the pending property is now a computed value that is only true when the status is actually pending (i.e., a request is in progress). When immediate: false is set, pending will be false until the first request is made. Previously, pending was always true until the first request was made, regardless of whether data was already cached or not. This change was made to align the meaning of pending with the status property and to avoid confusion in loading states [Alignment of pending value in useAsyncData and useFetch]. - If you are seeing pending: true even when data is present, it could be due to the experimental.pendingWhenIdle flag. By default, this flag is disabled, so pending should be false when idle (i.e., before the first request or when data is already cached). If you have enabled pendingWhenIdle: true in your Nuxt config, then pending will remain true until the first request is made, regardless of cached data [pendingWhenIdle]. What you should check: 1. Check your Nuxt config:
If you have set experimental.pendingWhenIdle: true, try removing or setting it to false to get the new, intended behavior.
export default defineNuxtConfig({
experimental: {
pendingWhenIdle: false,
},
})

export default defineNuxtConfig({
experimental: {
pendingWhenIdle: false,
},
})

2. Component logic:
Make sure your UI logic is using the new recommended pattern. Instead of relying solely on pending, consider using status for more precise control:
<template>
<div v-if="status === 'success'">
<p>Data: {{ data }}</p>
</div>
<div v-else>
<p>Loading...</p>
</div>
</template>
<script setup lang="ts">
const { data, pending, execute, status } = await useAsyncData(() => fetch('/api/data'), {
immediate: false
})
onMounted(() => execute())
</script>

<template>
<div v-if="status === 'success'">
<p>Data: {{ data }}</p>
</div>
<div v-else>
<p>Loading...</p>
</div>
</template>
<script setup lang="ts">
const { data, pending, execute, status } = await useAsyncData(() => fetch('/api/data'), {
immediate: false
})
onMounted(() => execute())
</script>

[Alignment of pending value in useAsyncData and useFetch] Summary:
If pending is true even when data is present, it's likely due to the pendingWhenIdle experimental flag or outdated logic expecting the old behavior. Update your config and UI logic as described above to resolve the issue. If you need the old behavior temporarily, you can enable pendingWhenIdle: true, but this is not recommended for new projects. If after these changes the issue persists, please double-check that your wrapper and usage are not overriding or masking the pending value from useAsyncData. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@1406829011761500240> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?