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
magic-amber•14mo 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.deep-jadeOP•14mo ago
@denis.monastyrskyi But then if I mount a component with
then it will fall out of sync with useAllOwnedTokensMetadata, wont it?
magic-amber•14mo 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 accounts
deep-jadeOP•14mo 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
magic-amber•14mo 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
deep-jadeOP•14mo 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
magic-amber•14mo 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 composedTokensMetadata
deep-jadeOP•14mo 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.
magic-amber•14mo 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 time
deep-jadeOP•14mo 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
magic-amber•14mo ago
['tokensMetadata', ownedTokens, ownedNfts, chain]
- TokensMetadata depends on [ownedTokens, ownedNfts, chain]
right or not?deep-jadeOP•14mo ago
Yes, but ownedTokens depends on accounts
So transitively tokensMetadata also depends on accounts
magic-amber•14mo 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