Client side request are not cached
Hi, sorry for the disturb.
I'm using the data cache api and I was wondering if it was the normal functioning of the plugin that the client side returns undefined as the cached value.
Is there a way to make this work on the client side too?
The module is specifically only made for SSR caching. Especially the unstorage dependency would have to be included in the client bundle for a seamless experience, which would not be that great. And it would then also only be compatible with the memory driver. Of course it would be possible to hardcode a memory cache into the client side code of the composable.
On the client side you already have Nuxt's own utilities such as useState or useAsyncData available to implement your own caching. For a seamless experience, useDataCache would have to pass the cached data back to the client as a payload so it's available on hydration. However, when used together with useState or useAsyncData, the same data would then be passed as payload twice.
However, I do see the value of having a single useDataCache composable that handles both server and client caching. I will keep this open to explore possible solutions.
Thank you for your quick response. The problem with useState and useAsyncData is that at the moment it should do at least one time a graphql call on client side. If the data already persist in the cache i'd like to avoid that graphql call.
I don't know if my thought is right but I hope it can be useful
Yeah I know exactly what you mean! Just using useAsyncData out of the box will only return a cached value on hydration. You'd have to define your own getCachedData method in useAsyncData to make it work. That would give you the possibility to return cached data from payload. And when using transform you could also cache subsequent GraphQL calls done inside useAsyncData.
Thank you and sorry again. I know that this question can riuslt annoying. What do you mean when you say "define my own getCachedData" method?
Do you think that a server endpoint that handle this for me can be a good solution? Or do you have an alternative idea?
🙏
You can pass a getCachedData method to the useAsyncData options: https://nuxt.com/docs/api/composables/use-async-data#params
By default, the getCachedData method is this:
key => nuxt.isHydrating ? nuxt.payload.data[key] : nuxt.static.data[key].
This will only load the cached data during hydration. But you can implement it as
key => nuxt.payload.data[key] || nuxt.static.data[key]
instead, which should also work after hydration.
Note that this only works on the client side. On the server these methods are not called, if I'm not mistaken.
Wow, simpler than i thought. It works fine with subsequent calls but in the client at the first access between one page and another it is always a new graphql when I am sure that the data has already been stored with the addToCache function.
export async function useGqlData({ key, query, variables }, args) {
const transform = args?.transform
const options = {
...args,
cacheKey: key,
transform: undefined,
}
const nuxt = useNuxtApp()
const { $graphqlApi } = nuxt
return useAsyncData(
key,
async () => {
const { value, addToCache } = await useDataCache(key)
if (value) {
return value
} else {
const res = await $graphqlApi({ query, variables })
if (res.error || res.errors || !res.data) {
console.error(res.error || res.errors || "No data found.")
throw new Error("Error in fetching data")
}
const result = transform ? transform(res.data) : res.data
if (key) {
addToCache(result, options.cacheTags, options.cacheExpires)
}
return result
}
},
{
...options,
getCachedData: (key) => {
return nuxt.payload.data[key] || nuxt.static.data[key]
},
}
)
}
This is my custom useAsyncData
I would try to move const { value, addToCache } = await useDataCache(key) outside of useAsyncData into your composable. You might also need to enable the experimental asyncContext feature of Nuxt for this to work properly. Also keep in mind you should await addToCache, because it's possible that it never stores in cache if execution continues.
@plcdnl In #58 a new composable called useCachedAsyncData was implemented that now also implements a client-side cache. The plan is to also add this functionality to useDataCache in #59.
I hope to release the new composable some time next week.
Wow! Incredible work. Thank you ! 🙏
As this has already been released in the last release, I'm going to close this issue.