React Query + Router
When using TanStack Query together with TanStack Router, I am not able to show fresh data even though my context is a query client, and I am invalidating the query client on mutation. Any clue?
My __root.tsx:
interface MyRouterContext {
queryClient: QueryClient;
}
export const Route = rootRouteWithContext<MyRouterContext>()({
component: App,
});
My main.tsx
const queryClient = new QueryClient({
defaultOptions: { queries: { refetchOnWindowFocus: false } },
});
const router = createRouter({
routeTree,
defaultPreload: "intent",
context: { queryClient },
});
And my Test.tsx
export const Route = createFileRoute("/Test")({
component: Test,
loader: ({ context: { queryClient } }) => queryClient.ensureQueryData(myQuery),
pendingComponent: Spinner,
errorComponent: Error,
});
myQuery:
export const myQuery = {
queryKey: ["test"],
queryFn: () => getSomething(),
};
And I have this functionality on a onClick button:
const { queryClient } = Route.useRouteContext();
<button onClick={() => queryClient.invalidateQueries(["test"])}>Click me</button>
11 Replies
deep-jadeOP•2y ago
I can see that my queries are inactive as I don't use them. This might seem like I cannot use useLoaderData as it does not ensure the data comes from react query?
@Tanner Linsley ? 🙂
This is in version 1.12.1
probable-pink•2y ago
You have to use useQuery
The loader is merely for prefetching
deep-jadeOP•2y ago
Ah. So what's the recommended way of doing this? Skip the loader part and use useQuery on mount of the component? If so, how can I still take advantage of pre-fetching the data and still be able to invalidate the data on mutations?
Thank you for responding by the way.
probable-pink•2y ago
You do both. Ensure the data in the loader. Use Query in the component
deep-jadeOP•2y ago
So like this?
export const Test = () => {
const { data } = useQuery(myQuery);
console.log("Data: ", data);
return <div>Test</div>;
};
export const Route = createFileRoute("/Test")({
component: Test,
loader: ({ context }) => context.queryClient.ensureQueryData(myQuery),
pendingComponent: Spinner,
errorComponent: Error,
});
export const myQuery = {
queryKey: ["test"],
queryFn: () => getTestData(),
};
Because this will trigger a refetch whenever the component mounts
But still it will use the same cache if I understand it correctly?probable-pink•2y ago
Yep
You want your loader to prefetch the data if there isn't anything in the cache
I can't remember if that's
ensureQuery or prefetchQuery
But the loader is just an optimization
Everything should work if you comment it outbroad-brown•2y ago
I am working on the exact same migration at the moment. I also tried to invalidateQueries but the loader wouldn't refetch the data. It would be great if the your insights here might be reflected in the current Router + Queries examples, this would make it easier to onboard users.
I will try the prefetchQuery approach
broad-brown•2y ago
I think this might be the best read to understand how it all works hand in hand, thanks @Tanner Linsley to point to the right direction:
https://tanstack.com/query/latest/docs/framework/react/guides/prefetching#router-integration
Prefetching & Router Integration | TanStack Query Docs
When you know or suspect that a certain piece of data will be needed, you can use prefetching to populate the cache with that data ahead of time, leading to a faster experience.
There are a few different prefetching patterns:
deep-jadeOP•2y ago
That makes sense, @Tanner Linsley ! Thanks. I agree with @dohomi , this should probably be mentioned in the examples. Because from what I could see, the recommended way was to use Router.useLoaderData() hook, which may be confusing since I was expecting the data to be active in React Query as I was using the context. I would gladly help creating an example if you would allow me? 🙂
probable-pink•2y ago
Good point. I can merge a PR or get to it a bit later
deep-jadeOP•2y ago
It should also be added to the example how we can prefetch invalidated queries when using Link.
E.g.: I'm on /test and moving to /test2, at test2 I invalidate a query that should be reflected at /test when moving back.
What do you think?
Maybe how we can use the shouldReload when queryKey gets invalidated? Any suggestions?
@Tanner Linsley