Dynamic dependent queries
Hi, I'm not sure what's the way to go about this situation
My idea was something like this
But I've heard it isn't recommended to call fetchQuery inside queryFn. So what's the right way to do this? Thanks!
13 Replies
sensitive-blue•17mo ago
Why don't you do it like this?
I'm not sure about
ownedNfts syntax, but everything else is just a simple chain of fetches, you don't need fetchQuery for it.sensitive-blueOP•17mo ago
@denis.monastyrskyi But then if I mount a component with
then it will fall out of sync with useAllOwnedTokensMetadata, wont it?
sensitive-blue•17mo ago
It's 2 different queries.
1.
['accounts', chain]
2.['composedTokensMetadata', chain]
They store different values. If you provide the same chain to both of them they will have the same accounts because you used the same endpoint for accounts in both of them, but they will make 2 separate request to get accountssensitive-blueOP•17mo ago
but suppose the user adds an account and i refetch [‘accounts’, chain]. Then there will be one more account returned by that query than [‘composedTokensMetadata’, chain] computes over, so there will be missing metadata for tokens owned by that new account
sensitive-blue•17mo ago
When you create a new account, you will probably use
useCreateAccountMutation. UseMutation has onSuccess hook where you should call queryClient.invalidateQueries and tell which queries should be refetched, In your case it will be
sensitive-blueOP•17mo ago
unfortunately the server is a third party service, so the react app only reads from it. Accounts are added by a completely separate mobile app
So the react app doesnt fire any mutations
This is why i need to refetch in intervals to detect changes in the server state
sensitive-blue•17mo ago
Then you must use this
['composedTokensMetadata', chain] only. It already incapsulates accounts, and you must use refetchInterval. You see, you can not rely on that your accounts will be in sync with other data, because even if you refetch accounts every 60 seconds where are guarantees that other data are in sync with accounts? Thus you must refetch all that composedTokensMetadatasensitive-blueOP•17mo ago
The server is guaranteed to be the source of truth. In the original example with useOwnedTokensMetadata, it all worked flawlessly, because the dependencies were encoded in the queryKeys. The problem is when I need to use useQueries.
It is not feasible to rely only on composedTokensMetadata, because it takes super long to fetch and some components only need the list of accounts.
sensitive-blue•17mo ago
useOwnedTokensMetadata - is a good solution. But if you want to refetch it every 60secs it is not different from what I suggessted. It's the same approach but on a different level.
useAllOwnedTokensMetadata - will be way worth, because if single call to useOwnedTokensMetadata creates a waterfall of 4 requests, then you can imagine what will happen if you call chains.map.
Here's what docs say:
Dependent queries by definition constitutes a form of request waterfall, which hurts performance. If we pretend both queries take the same amount of time, doing them serially instead of in parallel always takes twice as much timesensitive-blueOP•17mo ago
Yes the docs say that dependent queries by definition cause waterfalls, so they can't be avoided in this situation.
useOwnedTokensMetadata - is a good solution. But if you want to refetch it every 60secs it is not different from what I suggessted.I believe it is different, because the query key is effectively So if a refetch of ['accounts', query] introduces accounts with more tokens, then the queryKey for tokensMetadata will change and the queryFn will run. It's basically what the eslint rule encourages to keep everything in sync
sensitive-blue•17mo ago
['tokensMetadata', ownedTokens, ownedNfts, chain] - TokensMetadata depends on [ownedTokens, ownedNfts, chain] right or not?sensitive-blueOP•17mo ago
Yes, but ownedTokens depends on accounts
So transitively tokensMetadata also depends on accounts
sensitive-blue•17mo ago
[ownedTokens, ownedNfts] - depends on the account. So my solution was the same as your
Now you can continue to improve this and do this