T
TanStack•2y ago
deep-jade

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-jade
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
probable-pink•2y ago
You have to use useQuery The loader is merely for prefetching
deep-jade
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
probable-pink•2y ago
You do both. Ensure the data in the loader. Use Query in the component
deep-jade
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
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 out
broad-brown
broad-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
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-jade
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
probable-pink•2y ago
Good point. I can merge a PR or get to it a bit later
deep-jade
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

Did you find this page helpful?