Display cached data while refreshing in the background
I have a hook to fetch the same data on various pages that looks like this
It works fine, the data is fetched and the loading state is displayed on client if the data is missing when first navigating to the page. The issue is that when navigating away, then back, I can't figure out a way to make the data refresh quietly in the background (in case something changed on the server side) without triggering a loading state. Is there any way to achieve this behavior ?
5 Replies
Hi @Kérunix. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
Yes, you can achieve the behavior you want—displaying cached data immediately while refreshing in the background—using Nuxt’s built-in data fetching composables and utilities.
Key points:
- By default,
Call the
useAsyncData (and useLazyAsyncData) will show the cached data if available, and you can trigger a background refresh using the refresh method.
- The pending (or status) state will only be true if there is no cached data, or if you explicitly clear the data before refreshing.
- If you want to refresh data in the background (e.g., on page re-entry) without showing a loading state, you should:
- Display the cached data from the previous fetch.
- Call the refresh method manually (e.g., in a lifecycle hook like onMounted or onActivated).
- The pending state will only be true if there is no cached data, so your UI will not show a loading state unless the data is missing.
Example approach:
In your template, you can display the cached data immediately, and the refresh will happen in the background. The status will only be 'pending' if there is no cached data, so you can avoid showing a loading state when cached data is present.
References:
- The refresh method is the recommended way to refetch data in the background if you have access to the asyncData instance. This allows you to control when the refresh happens and how the UI responds to it. The cached data will be displayed while the refresh is in progress, unless you clear it manually refreshNuxtData.
- The default behavior of useAsyncData is to return cached data if available, and only set pending to true if there is no cached data useAsyncData - Return Values.
- You can use useNuxtData to access the cached value directly if needed useNuxtData.
Summary:Call the
refresh method in a lifecycle hook to refresh data in the background. The cached data will be displayed immediately, and the loading state will not be triggered unless the cache is empty. This matches the behavior you are looking for.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@189762782642569217> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@kapa.ai I tried something like this already. The issue is that when using multiple of these data fetching hooks in a single page, I get an error
onMounted is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup(). If you are using async setup(), make sure to register lifecycle hooks before the first await statement. with no request being fired.Let me check the knowledge base for you again. One moment! :books:
----------------------
You're encountering the error because Vue's lifecycle hooks like
Call
onMounted must be called synchronously during the execution of the setup() function, and before any await statements. When you use await useAsyncData(...) and then call onMounted, the hook is registered too late, outside the active component instance context, which triggers the error you described.
This is a known limitation of Vue's Composition API and is not specific to Nuxt. The Nuxt documentation also notes that if you use a custom wrapper around useAsyncData, you should avoid awaiting inside the composable, as it can cause unexpected behavior useAsyncData docs.
How to fix:
- Register lifecycle hooks like onMounted before any await statements in your composable.
- Instead of using await useAsyncData(...), return the promise and let the consuming component handle the await if needed, or use the returned refs directly.
Example adjustment:
Key point:Call
onMounted before any await in your composable, or avoid await entirely inside the composable. This will prevent the error and allow you to refresh data in the background as intended.
For more on this pattern and the warning about awaiting custom wrappers, see the Nuxt useAsyncData documentation and the section on custom useAsyncData wrappers.
If you need to await the data, do so in the consuming component, not inside the composable itself.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@189762782642569217> Kapa.ai is still learning and improving, please let me know how I did by reacting below.