diff --git a/docs/content/3.api/1.composables/use-async-data.md b/docs/content/3.api/1.composables/use-async-data.md index a1632812a07..de705641a25 100644 --- a/docs/content/3.api/1.composables/use-async-data.md +++ b/docs/content/3.api/1.composables/use-async-data.md @@ -23,6 +23,7 @@ type AsyncDataOptions = { pick?: string[] watch?: WatchSource[] initialCache?: boolean + immediate?: boolean } type AsyncData = { @@ -45,6 +46,7 @@ type AsyncData = { * _pick_: only pick specified keys in this array from the `handler` function result * _watch_: watch reactive sources to auto-refresh * _initialCache_: When set to `false`, will skip payload cache for initial fetch. (defaults to `true`) + * _immediate_: When set to `false`, will prevent the request from firing until the `refresh` function is called. Under the hood, `lazy: false` uses `` 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. diff --git a/docs/content/3.api/1.composables/use-fetch.md b/docs/content/3.api/1.composables/use-fetch.md index 258ae0af7af..5267c052cf7 100644 --- a/docs/content/3.api/1.composables/use-fetch.md +++ b/docs/content/3.api/1.composables/use-fetch.md @@ -24,6 +24,7 @@ type UseFetchOptions = { pick?: string[] watch?: WatchSource[] initialCache?: boolean + immediate?: boolean } type AsyncData = { @@ -52,6 +53,7 @@ type AsyncData = { * `watch`: watch reactive sources to auto-refresh * `initialCache`: When set to `false`, will skip payload cache for initial fetch. (defaults to `true`) * `transform`: A function that can be used to alter `handler` function result after resolving. + * `immediate`: When set to `false`, will prevent the request from firing until the `refresh` function is called. ::alert{type=warning} If you provide a function or ref as the `url` parameter, or if you provide functions as arguments to the `options` parameter, then the `useFetch` call will not match other `useFetch` calls elsewhere in your codebase, even if the options seem to be identical. If you wish to force a match, you may provide your own key in `options`. diff --git a/packages/nuxt/src/app/composables/asyncData.ts b/packages/nuxt/src/app/composables/asyncData.ts index a644d78f977..92d7a7d1897 100644 --- a/packages/nuxt/src/app/composables/asyncData.ts +++ b/packages/nuxt/src/app/composables/asyncData.ts @@ -30,6 +30,7 @@ export interface AsyncDataOptions< pick?: PickKeys watch?: MultiWatchSources initialCache?: boolean + immediate?: boolean } export interface RefreshOptions { @@ -95,6 +96,7 @@ export function useAsyncData< } options.lazy = options.lazy ?? (options as any).defer ?? false options.initialCache = options.initialCache ?? true + options.immediate = options.immediate ?? true // Setup nuxt instance payload const nuxt = useNuxtApp() @@ -163,23 +165,29 @@ export function useAsyncData< const fetchOnServer = options.server !== false && nuxt.payload.serverRendered // Server side - if (process.server && fetchOnServer) { + if (process.server && fetchOnServer && options.immediate) { const promise = initialFetch() onServerPrefetch(() => promise) } // Client side if (process.client) { - if (fetchOnServer && nuxt.isHydrating && key in nuxt.payload.data) { - // 1. Hydration (server: true): no fetch - asyncData.pending.value = false - } else if (instance && nuxt.payload.serverRendered && (nuxt.isHydrating || options.lazy)) { - // 2. Initial load (server: false): fetch on mounted - // 3. Navigation (lazy: true): fetch on mounted - instance._nuxtOnBeforeMountCbs.push(initialFetch) - } else { - // 4. Navigation (lazy: false) - or plugin usage: await fetch - initialFetch() + if (options.immediate) { + if (fetchOnServer && nuxt.isHydrating && key in nuxt.payload.data) { + // 1. Hydration (server: true): no fetch + asyncData.pending.value = false + } else if ( + instance && + nuxt.payload.serverRendered && + (nuxt.isHydrating || options.lazy) + ) { + // 2. Initial load (server: false): fetch on mounted + // 3. Navigation (lazy: true): fetch on mounted + instance._nuxtOnBeforeMountCbs.push(initialFetch) + } else { + // 4. Navigation (lazy: false) - or plugin usage: await fetch + initialFetch() + } } if (options.watch) { watch(options.watch, () => asyncData.refresh())