T
TanStack13mo ago
quickest-silver

Nuxt suspense component & vueQuery suspense in SSR app

What i try to do is using suspense in my page to show a fallback e.g. loading indicator as long as my vueQueries are fetching. For what i understand you await suspense() to make sure the data is fetched and available. I tried a lot of combinations but i never ever see the fallback when i excecuting a vueQuery query, it just renders the #default template when it is done fetching the data. Could that imply that my component is not async in the Suspense compontent context although i'm using script setup and await suspense() onMounted? Minimal Concept setup: page.vue
<template>
<main class="main">
<Suspense>
<template #default>
<HomePopularCategories />
</template>
<template #fallback>
<div>
<h1>WE ARE LOADING STUFF</h1>
</div>
</template>
</Suspense>
</main>
</template>
<template>
<main class="main">
<Suspense>
<template #default>
<HomePopularCategories />
</template>
<template #fallback>
<div>
<h1>WE ARE LOADING STUFF</h1>
</div>
</template>
</Suspense>
</main>
</template>
HomePopularCategories.vue
<script setup lang="ts">
...

const fetcher = async () => await getPopularCategories<PagePopularCategory[]>()

const { data: popularCategories, data, isLoading, isFetching, isError, status, suspense } = useQuery<PagePopularCategory[]>({
...queryKeys.pageConfig.hpPopCategories(),
queryFn: fetcher,
suspense: true,
enabled: process.client,
retry: false
} as UseQueryOptions<PagePopularCategory[], Error>);


onMounted(async() => {
await suspense()
})
</script>

<template>
<LayoutsPageSection class="p-categories__container" v-if="popularCategories">
<h1>WE ARE DONE LOADING STUFF</h1>
</LayoutsPageSection>
</template>
<script setup lang="ts">
...

const fetcher = async () => await getPopularCategories<PagePopularCategory[]>()

const { data: popularCategories, data, isLoading, isFetching, isError, status, suspense } = useQuery<PagePopularCategory[]>({
...queryKeys.pageConfig.hpPopCategories(),
queryFn: fetcher,
suspense: true,
enabled: process.client,
retry: false
} as UseQueryOptions<PagePopularCategory[], Error>);


onMounted(async() => {
await suspense()
})
</script>

<template>
<LayoutsPageSection class="p-categories__container" v-if="popularCategories">
<h1>WE ARE DONE LOADING STUFF</h1>
</LayoutsPageSection>
</template>
I use await suspense() a lot to make sure the data is loaded on serverside without the verbose isLoading and isError conditionals But i can not seem to get my head around this concept.
2 Replies
variable-lime
variable-lime13mo ago
For SSR you are looking for onServerPrefetch. I you want to suspense on the client just await directly in script setup https://tanstack.com/query/latest/docs/framework/vue/guides/ssr
SSR | TanStack Query Vue Docs
Vue Query supports prefetching multiple queries on the server and then dehydrating those queries to the queryClient. This means the server can prerender markup that is immediately available on page load and as soon as JS is available, Vue Query can upgrade or hydrate those queries with the full functionality of the library. This includes refetc...
quickest-silver
quickest-silverOP13mo ago
Thanks. That is what i'm doing in my composable to fetch data from the backend. The thing is, when i make these backend endpoints slow to send their response the app is busy fetching the data but does not show me the suspense fallback. It is just empty until the data is there. So that is where the Suspense component all stops making sense. It does not seem to trigger the fallback or bubble up to the parent when using await suspense() in a onServerPrefetch hook. For data retrieval it is wonderful, just await suspense and you are sure data will be there. But what i'm trying to figure out is how do i get to see one single loader in the time the data is being fetched for the script setup child components.

Did you find this page helpful?