Persisting @tanstack/vue-query query client in Quasar SSR

39 views Asked by At

Is there any way to persist data from server to client in SSR apart from using "store" in SSRContext? The docs mostly mention Vuex, even though Vuex is deprecated. I'm using @tanstack/vue-query, which saves a lot of headaches when managing async or server state. It manages deduping requests, retries, query caching and invalidation, gabarge collection, query refetching, infinite queries, and so much more. In the docs, the guidelines for integrating with Vite SSR are:

// main.js (entry point)
import App from './App.vue'
import viteSSR from 'vite-ssr/vue'
import {
  QueryClient,
  VueQueryPlugin,
  hydrate,
  dehydrate,
} from '@tanstack/vue-query'

export default viteSSR(App, { routes: [] }, ({ app, initialState }) => {
  // -- This is Vite SSR main hook, which is called once per request

  // Create a fresh VueQuery client
  const queryClient = new QueryClient()

  // Sync initialState with the client state
  if (import.meta.env.SSR) {
    // Indicate how to access and serialize VueQuery state during SSR
    initialState.vueQueryState = { toJSON: () => dehydrate(queryClient) }
  } else {
    // Reuse the existing state in the browser
    hydrate(queryClient, initialState.vueQueryState)
  }

  // Mount and provide the client to the app components
  app.use(VueQueryPlugin, { queryClient })
})

Then in the Vue component:

<!-- MyComponent.vue -->
<template>
  <div>
    <button @click="refetch">Refetch</button>
    <p>{{ data }}</p>
  </div>
</template>

<script setup>
  import { useQuery } from '@tanstack/vue-query'
  import { onServerPrefetch } from 'vue'

  // This will be prefetched and sent from the server
  const { refetch, data, suspense } = useQuery({
    queryKey: ['todos'],
    queryFn: getTodos,
  })

  onServerPrefetch(suspense)
</script>

I tried the same with boot files Quasar SSR, replacing initialState with ssrContext but it reads as undefined on the client.

Here is what I tried:

import { boot } from 'quasar/wrappers'
import { QueryClient, VueQueryPlugin, dehydrate, keepPreviousData } from '@tanstack/vue-query'
import { hydrate } from 'vue'

export default boot(({ app, ssrContext }) => {
  const globalQueryClient = new QueryClient({
    defaultOptions: {
      queries: {
        networkMode: 'always',
        placeholderData: keepPreviousData,
        retry: false,
        staleTime: 1000 * 60 * 5 // 5 minutes
      }
    }
  })
  if (process.env.SERVER) {
    // Indicate how to access and serialize VueQuery state during SSR
    ssrContext.vueQueryState = { toJSON: () => dehydrate(globalQueryClient) }
  } else {
    // Reuse the existing state in the browser
    hydrate(globalQueryClient, ssrContext.vueQueryState)
  }
  app.use(VueQueryPlugin, { queryClient: globalQueryClient })
})

vueQueryState was undefined on the client.

0

There are 0 answers