Calling queries in effects
Is there any way to have a lazy query? Eg:
What I'm ultimately trying to do is defer invoking the query until the args satisfy some checks, and then I wish to debounce the query execution.
20 Replies
If you don't care about reactivity, I think the easiest way to do this is with the
ConvexHttpClient
. You could do something like:
https://docs.convex.dev/api/classes/browser.ConvexHttpClient#queryClass: ConvexHttpClient | Convex Developer Hub
browser.ConvexHttpClient
I do care about reactivity, i just want a way to throttle when and how often the query is executed
Here's an article @ian wrote that might help with part of what you're looking for: https://stack.convex.dev/throttling-requests-by-single-flighting
Throttling Requests by Single-Flighting
For write-heavy applications, use single flighting to dynamically throttle requests. See how we implement this with React hooks for Convex.
Ahh I see. And under what circumstances are you worried about it executing too often?
Actually never mind, that article is about mutations not queries π Might be helpful either way.
One way to defer loading the query is to use a sub-component that is conditionally mounted and load the query there.
You can also throttle changing the props on the sub-component so that the query isn't re-requested too often
For more context, this is essentially a type-ahead implementation. The value being queried changes with every keystroke. I want to debounce it and also not execute it until 3 characters entered
Got it. Yeah then I think having a few levels of components would solve this. Something like:
Typeahead
:
- has state for the user input
- If the input is >3 charaters mount TypeaheadResults
- Throttles prop updates to TypeaheadResults
TypeaheadResults
:
- loads results with useQuery
Yeah. seems to be getting a bit cute, especially if the component destructuring serves no other purpose.
Be great to get something similar to Apollo's approach. https://www.apollographql.com/docs/react/data/queries/#manual-execution-with-uselazyquery
that or perhaps options that could be passed to
useQuery
with settings like enabled
and throttle
It's actually not possible if you want reactivity!
Using a lazy approach like Apollo's means that you'll only get a query result when you call the getter. It doesn't give us a way to rerender with the new query result if the data on the server changes
or perhaps options that could be passed to useQuery with settings like enabled and throttleYep, thanks for the feedback! We've talked about adding things like this in the past and this is one more vote for doing it
Understood -- then perhaps my second proposal makes sense.
@allen possible some of the hints in this article are relevant: https://stack.convex.dev/help-my-app-is-overreacting. -- the overall suggestion being to use combinators to get the kind of reactivity you want. there is probably a useDebouncedQuery(ms, ...) sort of combinator that would do what you want that wraps
useQuery
"updating too often" is in the class of things like "updating before the user is ready" that are addressed in there and in https://stack.convex.dev/coping-with-the-web-s-looming-global-reactivity-crisis
Managing Reactivity with useBufferedState
Reactivity has taken a dominant position today within web app development. Our components and app state are all reactive, and the world has adaptedβmo...
Thanks, @jamwt. I'll take a look.
Probably some reactivity patterns I just need to lean into harder.
Yep hooks are another powerful pattern here! Keep in mind though that hooks canβt be called conditionally. So in @jamwtβs example, your component would always call useQuery, it just might not use the result (or use an old result) while rendering
You could have a hook that denounces the arguments and uses an old version of them. But annoyingly a proper conditional hook that sometimes doesnβt load the query is impossible in React
I'm a bit late to this party, but I'll add another vote to get a
lazyQuery
hook, it'd be very useful in situations when searching. I solved it by conditionally passing the "skip"
string if there are no args to pass.Hey @π πππππ¬, can you say more about this case? Would calling the query as a one-shot work for you here, like https://docs.convex.dev/client/react#one-off-queries
YES! That's exactly what I was looking for! I thought I had looked everywhere in the docs for it, should've looked for "one-off" and not "lazy" π