N
Nuxt5d ago
zangetsu

Nuxt 3.16.1 - getCachedData not working (?)

Hi, I was watching a video by Alexander Lichter about caching API calls in Nuxt and decided to test this approach in my Nuxt app. I copied and pasted the code exactly as shown:
const { data } = await useFetch<any>('https://icanhazdadjoke.com/', {
headers: {
Accept: 'application/json',
},
transform(input) {
return {
...input,
fetchedAt: new Date(),
}
},
getCachedData(key) {
const data = nuxtApp.payload.data[key] || nuxtApp.static.data[key]
// If data is not fetched yet
if (!data) {
// Fetch the first time
return
}

// Is the data too old?
const expirationDate = new Date(data.fetchedAt)
expirationDate.setTime(expirationDate.getTime() + 10 * 1000)
const isExpired = expirationDate.getTime() < Date.now()
if (isExpired) {
// Refetch the data
return
}

return data
},
})
const { data } = await useFetch<any>('https://icanhazdadjoke.com/', {
headers: {
Accept: 'application/json',
},
transform(input) {
return {
...input,
fetchedAt: new Date(),
}
},
getCachedData(key) {
const data = nuxtApp.payload.data[key] || nuxtApp.static.data[key]
// If data is not fetched yet
if (!data) {
// Fetch the first time
return
}

// Is the data too old?
const expirationDate = new Date(data.fetchedAt)
expirationDate.setTime(expirationDate.getTime() + 10 * 1000)
const isExpired = expirationDate.getTime() < Date.now()
if (isExpired) {
// Refetch the data
return
}

return data
},
})
However, when I debug nuxtApp.payload.data or nuxtApp.static.data[key], even if the API has been called 40 times, Nuxt doesn't save the data. I even added this to my nuxt.config:
export default defineNuxtConfig({
experimental: {
payloadExtraction: true,
},
}
export default defineNuxtConfig({
experimental: {
payloadExtraction: true,
},
}
8 Replies
kapa.ai
kapa.ai5d ago
Hi @zangetsu. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- It seems you're experiencing an issue with the getCachedData functionality in Nuxt 3.16.1. There are a few potential reasons why your caching implementation isn't working as expected. Possible Issues 1. Automatic Cache Purging In Nuxt 3.16.0 and later, there's a new experimental feature called purgeCachedData that's enabled by default. This feature automatically purges cached data from useAsyncData and nuxtApp.static.data on route navigation to prevent memory leaks and ensure fresh data is loaded when needed. You might need to disable this feature if you want to maintain your cached data:
export default defineNuxtConfig({
experimental: {
payloadExtraction: true,
purgeCachedData: false
},
})
export default defineNuxtConfig({
experimental: {
payloadExtraction: true,
purgeCachedData: false
},
})
Nuxt Configuration Documentation explains this feature in detail. 2. Key Generation Issues There's a known issue in recent Nuxt versions where the key generation for payloads can be inconsistent between server and client. This can cause the client to make new requests instead of using cached data. Try explicitly defining a key in your useFetch call:
const { data } = await useFetch<any>('<https://icanhazdadjoke.com/',> {
key: 'dad-joke',
// rest of your options...
})
const { data } = await useFetch<any>('<https://icanhazdadjoke.com/',> {
key: 'dad-joke',
// rest of your options...
})
This issue was discussed in GitHub Issue #31355. 3. Hydration Issues Some users have reported that switching from useFetch to useAsyncData with $fetch can help resolve caching issues:
const { data } = await useAsyncData(
'dad-joke',
() => $fetch('<https://icanhazdadjoke.com/',> {
headers: {
Accept: 'application/json',
}
}),
{
transform(input) {
return {
...input,
fetchedAt: new Date(),
}
},
getCachedData(key) {
// Your caching logic here
}
}
)
const { data } = await useAsyncData(
'dad-joke',
() => $fetch('<https://icanhazdadjoke.com/',> {
headers: {
Accept: 'application/json',
}
}),
{
transform(input) {
return {
...input,
fetchedAt: new Date(),
}
},
getCachedData(key) {
// Your caching logic here
}
}
)
4. Check Your Nuxt Version Make sure you're using the exact version where this feature is fully supported. The getCachedData functionality has been improved in various releases. Additional Troubleshooting 1. Try using browser developer tools to inspect the network requests and see if requests are being made repeatedly. 2. Verify that your transform function is working correctly by logging the transformed data. 3. Consider implementing a simpler version of getCachedData first to test if the basic caching mechanism works before adding expiration logic. If none of these solutions work, it might be worth checking if there are any specific issues with Nuxt 3.16.1 related to caching in the Nuxt GitHub repository. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@745078500255596646> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
manniL
manniL5d ago
Do you use SSR?
zangetsu
zangetsuOP5d ago
yep i got it, i was using this code on a component inside a v-for, moving it on the parent component fixed this behavior, im still wondering why it wasn't caching btw
manniL
manniL5d ago
just checked the stackblitz with the latest code and it should work there too https://stackblitz.com/github/TheAlexLichter/nuxt-get-cached-dat
StackBlitz
StackBlitz
manniL
manniL5d ago
ahh, okay. Do you have an example?
zangetsu
zangetsuOP5d ago
Parent.vue
<script setup>

// Here is caching
const url = '/api/tipologiche/tematiche_secondarie'
const options = useCachedData().useFetchOptions({ url })
const { data: tematiche } = useFetch<JsonLdCollection<ITipologica>>('/api/tipologiche/tematiche_secondarie', options)

const rows = [...]
</script>

<template>

<table>
<tbody>
<tr v-for="row in rows">
<child-component :row />
</tr>
</tbody>
</table>
</template>
<script setup>

// Here is caching
const url = '/api/tipologiche/tematiche_secondarie'
const options = useCachedData().useFetchOptions({ url })
const { data: tematiche } = useFetch<JsonLdCollection<ITipologica>>('/api/tipologiche/tematiche_secondarie', options)

const rows = [...]
</script>

<template>

<table>
<tbody>
<tr v-for="row in rows">
<child-component :row />
</tr>
</tbody>
</table>
</template>
Child.vue
<script setup lang="ts">

const props = defineProps<{row: any}>()
// making api call every time it is instantiated
const url = '/api/tipologiche/tematiche_secondarie'
const options = useCachedData().useFetchOptions({ url })
const { data: tematiche } = useFetch<JsonLdCollection<ITipologica>>('/api/tipologiche/tematiche_secondarie', options)

</script>

<template>
{{tematiche.includes(row) ? 'yes' : 'no'}}
</template>
<script setup lang="ts">

const props = defineProps<{row: any}>()
// making api call every time it is instantiated
const url = '/api/tipologiche/tematiche_secondarie'
const options = useCachedData().useFetchOptions({ url })
const { data: tematiche } = useFetch<JsonLdCollection<ITipologica>>('/api/tipologiche/tematiche_secondarie', options)

</script>

<template>
{{tematiche.includes(row) ? 'yes' : 'no'}}
</template>
the useCachedData is the wrapper of your code It's strange, so I can't cache API calls that are made by a sub-component?:usefetchwrong:
zangetsu
zangetsuOP5d ago
https://stackblitz.com/~/github.com/zangetsu02/nuxt-get-cached-data I created a repository for reproduction. The Test.vue component makes API calls to the same URL, so it always responds the same. I expect that the first time it is rendered by the v-for, it caches the data.
No description

Did you find this page helpful?