Closed manuelarling closed 4 weeks ago
You are right.
This is due to the fact that in Vue2, Vue instance is shared across requests. Clearing it between requests is not enough, cause there might be couple requests in-flight at the same time.
I believe you might achieve proper per-request separation with slight modification of the plugin and component code.
Plugin code:
import Vue from "vue";
import { VueQueryPlugin, QueryClient, hydrate } from "@tanstack/vue-query";
export default (context) => {
// Modify your Vue Query global settings here
const queryClient = new QueryClient({
defaultOptions: { queries: { staleTime: 5000 } },
});
if (process.server) {
context.ssrContext.VueQuery = queryClient;
}
if (process.client) {
Vue.use(VueQueryPlugin, { queryClient });
if (context.nuxtState && context.nuxtState.vueQueryState) {
console.log(
"Hydrating state from server",
context.nuxtState.vueQueryState
);
hydrate(queryClient, context.nuxtState.vueQueryState);
}
}
};
In component, move queryClient
retrieval to the top and pass queryClient
to each useQuery
call as a second parameter:
const { ssrContext } = useContext();
const queryClient = (ssrContext != null && ssrContext.VueQuery) || useQueryClient()
const { data: data1, suspense } = useQuery({
queryKey: ["todos"],
queryFn: fetcher,
}, queryClient);
First of all, thank you for your reply that helped a lot.
I was missing the first information, and then I did some more research. I found out that the problem is also called cross-request state pollution
. The difference in the two examples in the documentation is that the Nuxt 3 example uses the useState
Composable. This fixes the problem by creating a separate state object for each request.
In any case, I would expect the two examples in the documentation to have the same behavior, or at least in the Nuxt 2 example a hint of the potential problem.
Yes, I am looking for a solution that implements a version for creating queryClient per request. Is there perhaps another suggestion, as unfortunately this one requires a lot of refactoring and also attention must be paid in the future.
Docs have been updated.
Difference in behavior is because in Vue2 Vue instance is shared between requests.
If you find a better way to simplify Nuxt2 setup, please open a PR.
Describe the bug
The behavior for
queryClient
using server-side rendering is different and works incorrectly in Nuxt2/Vue2. On Nuxt3/Vue3 the expected behavior occurs.In Nuxt 3, the
queryCache
is likely reset for each request. This is not the case in Nuxt 2.This leads to unexpected behavior in the following example use case. When user 1 requests a page, the list of to-dos belonging to user 1 is fetched and displayed. User 2 then accesses the site, but when the page is loaded on the client, the list of to-dos belonging to User 1 is displayed, and the to-dos belonging to User 2 are not displayed until after the refetch on the client page. This creates a privacy issue.
This use case is shown as an example in the two repos. To simulate two different users, the url param is set differently. This is to symbolize the different responses from a server.
Your minimal, reproducible example
Nuxt 2: https://codesandbox.io/p/devbox/gracious-hermann-lkc3rq?workspaceId=684c7eda-e5ab-41ca-9242-874b5f17c5ae
Nuxt 3: https://codesandbox.io/p/devbox/proud-wood-h3syhd?workspaceId=684c7eda-e5ab-41ca-9242-874b5f17c5ae
Steps to reproduce
/abc
/123
Do this for both repos and you will see that the behavior is different and you will see that the logs in the browser devtools and the terminal are different.
Expected behavior
The Behaviour on Nuxt2/Vue2 should be the same as on Nuxt3/Vue3.
How often does this bug happen?
Every time
Screenshots or Videos
Nuxt 2:
https://github.com/user-attachments/assets/574214fb-b50e-4af0-84d2-b5a2cfe15588
Nuxt 3:
https://github.com/user-attachments/assets/b5715d5e-4fa0-4023-a646-4331a83cbc8a
Platform
Tanstack Query adapter
vue-query
TanStack Query version
v5.51.21
TypeScript version
No response
Additional context
No response