Repository: nuxt/nuxt
File: packages/nuxt/src/app/composables/asyncData.ts (TypeScript)

Code before:
          asyncData.error.value = createError<NuxtErrorDataT>(error) as (NuxtErrorDataT extends Error | NuxtError ? NuxtErrorDataT : NuxtError<NuxtErrorDataT>)
          asyncData.data.value = unref(options.default!())
          asyncData.status.value = 'error'
        })
        .finally(() => {
          if ((promise as any).cancelled) { return }

          if (pendingWhenIdle) {
            asyncData.pending.value = false
          }

          delete nuxtApp._asyncDataPromises[key]
        })
      nuxtApp._asyncDataPromises[key] = promise
      return nuxtApp._asyncDataPromises[key]!
    },
    _execute: debounce((...args) => asyncData.execute(...args), 0, { leading: true }),
    _default: options.default!,
    _deps: 0,
    _init: true,
    _hash: isDev ? createHash(_handler, options) : undefined,
    _off: () => {
      unsubRefreshAsyncData()
      asyncData._init = false
      // TODO: disable in v4 in favour of custom caching strategies
      if (purgeCachedData && !hasCustomGetCachedData) {
        clearNuxtDataByKey(nuxtApp, key)
        asyncData.execute = () => Promise.resolve()
      }
    },
  }

  return asyncData
}

// Used to get default values
const getDefault = () => asyncDataDefaults.value
const getDefaultCachedData: AsyncDataOptions<any>['getCachedData'] = (key, nuxtApp, ctx) => {
  if (nuxtApp.isHydrating) {
    return nuxtApp.payload.data[key]
  }

  if (ctx.cause !== 'refresh:manual' && ctx.cause !== 'refresh:hook') {
    return nuxtApp.static.data[key]
  }
}

function createHash (_handler: () => unknown, options: Partial<Record<keyof AsyncDataOptions<any>, unknown>>) {
  return {
    handler: hash(_handler),
    transform: options.transform ? hash(options.transform) : undefined,

Review comment (bug):
It would help to add a comment here explaining why the call to nextTick is required, referencing the transition bug and the linked issue for future maintainability.
```suggestion
      if (purgeCachedData && !hasCustomGetCachedData) {
        // Using nextTick to ensure this cleanup logic runs after the current DOM update cycle.
        // This addresses a known transition bug. See https://github.com/nuxt/nuxt/issues/12345 for details.
```

Code after:
          asyncData.error.value = createError<NuxtErrorDataT>(error) as (NuxtErrorDataT extends Error | NuxtError ? NuxtErrorDataT : NuxtError<NuxtErrorDataT>)
          asyncData.data.value = unref(options.default!())
          asyncData.status.value = 'error'
        })
        .finally(() => {
          if ((promise as any).cancelled) { return }

          if (pendingWhenIdle) {
            asyncData.pending.value = false
          }

          delete nuxtApp._asyncDataPromises[key]
        })
      nuxtApp._asyncDataPromises[key] = promise
      return nuxtApp._asyncDataPromises[key]!
    },
    _execute: debounce((...args) => asyncData.execute(...args), 0, { leading: true }),
    _default: options.default!,
    _deps: 0,
    _init: true,
    _hash: isDev ? createHash(_handler, options) : undefined,
    _off: () => {
      unsubRefreshAsyncData()
      asyncData._init = false
      // TODO: disable in v4 in favour of custom caching strategies
      if (purgeCachedData && !hasCustomGetCachedData) {
        nextTick(() => {
          if (!asyncData._init) {
            clearNuxtDataByKey(nuxtApp, key)
            asyncData.execute = () => Promise.resolve()
          }
        })
      }
    },
  }

  return asyncData
}

// Used to get default values
const getDefault = () => asyncDataDefaults.value
const getDefaultCachedData: AsyncDataOptions<any>['getCachedData'] = (key, nuxtApp, ctx) => {
  if (nuxtApp.isHydrating) {
    return nuxtApp.payload.data[key]
  }

  if (ctx.cause !== 'refresh:manual' && ctx.cause !== 'refresh:hook') {
    return nuxtApp.static.data[key]
  }
}