#Nuxt3 useLazyFetch's and useFetch's key property isn't working

16 messages · Page 1 of 1 (latest)

sly pendant
#

I am using useLazy fetch in a very simple two page application, i have passed a constant string as a key to useLazyFetch, but upon navigating to profile page and coming back to index page it again fetches the data.

pages/index.vaue

<template>
    <div v-if="listPending">{{ listPending }}</div>
    <div v-else>{{ countryList }}</div>
</template>

<script setup>

const URL = "https://fakestoreapi.com/products?limit=5";

let {pending: listPending, data: countryList} = useLazyFetch(`${URL}/countryList`, {
    key: URL
});

</script>

pages/profile.vue

<template>
  Profile Page
</template>

and below is the layouts/default.vue i use this to navigate between pages

<template>
    <div>
        <NuxtLink to="/">Dashboard</NuxtLink>
        <NuxtLink to="profile">Profile</NuxtLink>
    </div>

    <slot/>
</template>

am i using the key option in a wrong way ? i also tried passing key="qwerty", but it still refetches the data upon page navigation.

sly pendant
safe osprey
rough crater
#

The key is used in useFetch to handle data de-duplication during the hydration process when rendering a server-rendered page. The key helps in mapping the result of the server-side fetch to the client-side component data, preventing the data from being fetched more than once between the server and client

It won't cache the results on the client-side across multiple requets.

#

I create my own composable using $fetch and Nuxt's payload to truly cache data across multiple requests.

But @cobalt quest may have some insight into whether that is right approach or not.

safe osprey
#

Then I think documentation doesn't explain it well. SInce there is not mention of server-client comunication, it just says:

data fetching can be properly de-duplicated across requests

#

@rough crater is your approach similar to Singleton pattern? If, for the given request, there is an identical pending request, just stick to existing one and return it's response as soon as resolved?

rough crater
#

My approach is something like this

export async function useApi<T>({ path, cacheKey, fetchOptions }: UseApiArgs): Promise<{
    data: T | null;
    error: boolean;
}> {
    const nuxtApp = useNuxtApp();

    if (cacheKey) {
        const cachedData = nuxtApp.payload.data[cacheKey] as {
            data: T | null;
            error: boolean;
        };

        if (cachedData) {
            return cachedData;
        }
    }

    
    let response;

    try {
        const data = await $fetch<T>(path, fetchOptions || {});

        response = { data, error: false };
    } catch (error) {
        response = { data: null, error: true };
    } finally {
        if (cacheKey) {
            nuxtApp.payload.data[cacheKey] = response;
        }
    }

    return response;
}
#

so this will talk to my api, if we already have data, return the data. otherwise, make the call.

And since data is cached in nuxt payload, this will work across server/client during hydration.

#

The reason I went with $fetch is because i use the function in middleware, where useFetch cannot be used

#

If you are using it only in components, you could just create a tiny wrapper around useFetch itself. Which will be much simpler

safe osprey
#

Thanks for the info and your code snippet! Yeah, I meant something similar but didn't know about nuxtApp.payload thing. I'll give it a try today.

rotund tide
#

I'm running into this as well. Here's a minimal repro: https://stackblitz.com/edit/github-qj42c9?file=app.vue app.vue calls useFetch to perform a GET upon page load, and if I re-use the useFetch key and later perform a PATCH, the data from my initial GET call gets overwritten even though I'm not overwriting it with the result of the PATCH. I think I might have to set my useFetch key to something like <http verb> + <resource path> to avoid PATCHes clobbering the underlying data from GETs.

Create a new Nuxt project, module, layer or start from a theme with our collection of starters.

safe osprey
#

Oh, I assume different methods shouldn't overwrite each other.
I don't think that methods like POST, PUT, PATCH should be cached at all (unless explicitly opt-in by developer)