Fuzzyma
Fuzzyma2mo ago

Why isnt `useQuery` returning a cached result right away?

When i use convex.query(someQuery) in a loader and in a sub component i use useQuery(someQuery), the query doesn't return a result right away. I would have expected that the value is cached somehow. Isn't that the case? I would love to use loaders to ensure data is there but i don't want to use useLoaderData() because I loose the real time capabilities of the one-off-query i request in the loader Any insights would be appreciated. The docs say
Convex caches query results automatically. If many clients request the same query, with the same arguments, they will receive a cached response.
So I expected an instant result. But its always undefined first which leads to flashing of wrong component state
Queries | Convex Developer Hub
Fetch data from the database with caching and reactivity
21 Replies
Convex Bot
Convex Bot2mo ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
Michal Srb
Michal Srb2mo ago
@Fuzzyma also note the difference between caching on the convex backend (you can see which queries are cached in Logs on your dashboard) and the client having the query results loaded up (only that gives you "instant response", otherwise you need to wait on client->server roundtrip).
Fuzzyma
FuzzymaOP2mo ago
Isnt that specific to tanstacks react-query? I use convex as is. I am also using react-router and not tanstack-router but I guess that makes no difference i am certainly talking about "loaded" queries. The same query is executed in the loader (or a parent component) before and it still flashes because it has to reload. Isnt there any client side query caching? would be cool if this function was available on the ConvexReactClient . but that has only prewarmQuery which is not what I need
deen
deen2mo ago
The Convex server caches the result of the query, so it does not need to retrieve it from the database again. The client library does not "cache" anything, but it maintains the results of queries it is subscribed to. The one-off query is not a subscription, it simply retrieves the data and returns it to you. If you're seeing a flash, it's because you're not using the data you loaded. You could use it like this:
const value = valueFromUseQuery ?? valueFromLoader
const value = valueFromUseQuery ?? valueFromLoader
Fuzzyma
FuzzymaOP2mo ago
good idea! So is this true for every time i use useQuery sometimes? Convex makes it really convenient to only pass around ids instead of results so I do that quite often. I use useQuery of the same thing especially when navigating to a subpage. Does that mean, it will always reload those queries because they are not cached? I would have thought that same queries share same results (i am specifically asking not about conex.query here but multiple useQuery that query the same thing)
deen
deen2mo ago
No, they are shared, and it will appear instantly, because it's the same subscription. This is an extremely convenient way to share the same data around your application. But if your page navigation unmounts every useQuery hook before your next is mounted, it will drop the subscription instantly. convex-helpers has a query cache that can help with this. Or, if you're keeping it mounted somewhere high up that survives the page transition, that would work too.
Fuzzyma
FuzzymaOP2mo ago
yes i read about that one! I assume that I have to use that since the query subscriptions are not above page level and I am switching pages when i navigate after all ok this is enlightening! Will try to apply and test it
deen
deen2mo ago
I pretty much always use it. And unless you're doing server-side rendering, I would just drop the loaders entirely, since you'll just be making extra queries for no reason. They're solving a problem with traditional HTTP calls that convex doesn't really have.
Fuzzyma
FuzzymaOP2mo ago
The reason i wanted loaders in the first place is, that it would flicker between states. And I wanted a nice layer that ensures that all data is available before I render the actual page. E.g. I am changing a header if the active team is the personal team and I cant say if its personal or not before its loaded. So everytime i visit that page it flickers. I have similar things at other places - it would just be awesome to load the queries I need for the next page before going to that page so its all there instantly and I dont see a single spinner I think loaders have a good reason to exist even on client side apps for that exact reason. Maybe you have a better way of dealing with that?
deen
deen2mo ago
The loaders do make that issue go away, if you're OK with repeating the queries. Only TanStack has been blessed with proper support here. Try the query cache out with the loaders disabled so that you can observe what they're doing. Maybe you can clone the behaviour, or find another way.
Fuzzyma
FuzzymaOP2mo ago
So if I wrap my queries with tanstack queries as explained in the docs, would that solve the problem? I am using tanstack queries for actions already anyways so i might as well go the full route. I am not glued to react router either
deen
deen2mo ago
https://docs.convex.dev/client/react/tanstack-start/ to get the benefits you would have to drop react router and use tanstack start. i can't say if that's worth it to you, but you would be using a supported framework rather than on your own
TanStack Start | Convex Developer Hub
How Convex works with TanStack Start
deen
deen2mo ago
although maybe #remixjs has useful info, which i just remembered exists
Fuzzyma
FuzzymaOP2mo ago
Yeah, my project is historically grown. I didnt know that there would be so many implications when choosing something like a router lol. I also didnt want any server rendering and tanstack start sounds like you are getting the whole pack. But i might give in. That said, I think adding support for other routers would be as simple as exposing the ability to add a subscription yourself and check the local cache (something like the ensureQueryData thing)
Michal Srb
Michal Srb2mo ago
@Fuzzyma besides Tanstack, you can also use preloadQuery (it's in convex/next, but will work in RR if you configure it): https://docs.convex.dev/client/react/nextjs/server-rendering#preloading-data-for-client-components The "keyword" which is implied in your original question but not mentioned is server rendering. RR loaders fetch data on the server.
Next.js Server Rendering | Convex Developer Hub
Implement server-side rendering with Convex in Next.js App Router using preloadQuery, fetchQuery, and server actions for improved performance.
Fuzzyma
FuzzymaOP2mo ago
I am not doing server rendering. I want to use loaders on the client side to get rid of the spinner-waterfalls are you saying that I can just use nexts preloadQuery on the client and it just works? It doesnt look like this is the case since preloadQuery should be used in the server component At least it seems like that from looking at the link you sent
Michal Srb
Michal Srb2mo ago
You can get rid of a waterfall by moving to a single useQuery at the top of your tree. This does interplay with caching, and there’s no sub-query caching in Convex yet I’m afraid.
TeeLusk
TeeLusk2mo ago
New to convex, but what type of configuration would be needed?
Mika
Mika2mo ago
Make sure to check out Query Caching https://www.youtube.com/shorts/Mwlh_fn5Ftg as it is exactly what I needed and not too advertised
Michal Srb
Michal Srb2mo ago
You need to give it the url of your Convex backend.

Did you find this page helpful?