Lucas Couto
Lucas Couto3mo ago

Query arguments issue?

Came across an interesting problem that I was hoping to get some help with. Basically I have a query that receives a timestamp as an argument to control what information is returned. This argument will change in certain key situations. I know the default Convex behavior is to create a new subscription for each set of arguments, but I don't want all these subscriptions active because those will consume too much data. Is there a way to close unwanted subscriptions?
9 Replies
Convex Bot
Convex Bot3mo 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!
lee
lee3mo ago
When the useQuery is unmounted (in the React sense), the subscription is dropped and Convex stops running it. Are you okay with a new query running every time the timestamp arg changes? That's what's happening; it's replacing the queries at previous timestamps
Lucas Couto
Lucas CoutoOP3mo ago
It's fine running a new query. The problem is that all previous subscriptions for different timestamps are still active. Adding a console.log does print each previous timestamp. I don't really have the option to unmount the component. The main thing I'm trying to address with this timestamp is that I need this function to return only what actually changed between calls, not just a full result object every time.
lee
lee3mo ago
Oh okay. Well you can get more control of the subscription lifetime by using the underlying watchQuery method https://docs.convex.dev/api/classes/react.ConvexReactClient#watchquery
lee
lee3mo ago
Like
const convex = useConvex();
const useEffect(() => {
const watch = convex.watchQuery(...);
const unsubscribe = watch.onUpdate(() => {
const newValue = watch.localQueryResult();
// do something with new value
});
// put the unsubscribe function somewhere so you can call it later
});
const convex = useConvex();
const useEffect(() => {
const watch = convex.watchQuery(...);
const unsubscribe = watch.onUpdate(() => {
const newValue = watch.localQueryResult();
// do something with new value
});
// put the unsubscribe function somewhere so you can call it later
});
```
Lucas Couto
Lucas CoutoOP3mo ago
Hey @Lee! We did end up going with watchQuery. It worked like a charm, thank you very much for your help 😁
lee
lee3mo ago
That's awesome! If you want to write it up and share (maybe #show-and-tell ) , this sounds like an interesting pattern others could learn about
Tom Redman
Tom Redman3mo ago
I didn’t know about this. Would love to see it @Lucas Couto!
Lucas Couto
Lucas CoutoOP2mo ago
Unfortunately I don't have the time to write a full example, but I ended up following basically what @lee shared above. Every time your query params change, Convex creates a new subscription for the new group of params. Usually it's not a problem since components tend to get destroyed and then rebuilt quite often, but in our case that was just not an option. So I ended up following this pattern:
const convex = useConvex();

useEffect(() => {
const watch = convex.watchQuery(api.table.getTableData, {
param1: param1,
param2: param2,
timestamp: timestamp,
});

const unsubscribe = watch.onUpdate(() => {
// In here I have some checks to make sure it is ok to unsubscribe, but then just call the function.
unsubscribe();
});
}, [param1, param2, timestamp]);
const convex = useConvex();

useEffect(() => {
const watch = convex.watchQuery(api.table.getTableData, {
param1: param1,
param2: param2,
timestamp: timestamp,
});

const unsubscribe = watch.onUpdate(() => {
// In here I have some checks to make sure it is ok to unsubscribe, but then just call the function.
unsubscribe();
});
}, [param1, param2, timestamp]);
Also probably worth noting that in my case, having the return of the useEffect unsubscribe was not a good option because that meant subscriptions were getting removed even when they were not supposed to. That's mainly because of how I had to structure the logic in the hook and there were some params in my dependency array that would trigger it (which in turn destroyed the subscription I wanted to keep alive) after my subscription was created.

Did you find this page helpful?