What's a robust way to define a dependent query when using `useQueries`?
I would like to use
useQueries for parallel queries that are based on a dependent list of unknown length. Normally dependent queries would use the enabled option to specify whether or not the prerequisite data is ready to allow the query to run, but that's not an option at the top level for useQueries. I saw on the github forums that you can pass an empty array to it to have it do a no-op but my concern with that is that the not yet loaded state then looks identical to an empty list response from the providing query. While it is possible to look at the loading state of the providing query, my concern is that it would be easy to pass the array result of the dependent useQueries to another context elsewhere and lose that information if you forget to also send the dependent query loading state with it as well as it would just be an array without any state information. With a non parallel dependent query the state of the query is encoded in the query result while the providing query is still loading so I think not having that state information coupled with the useQueries result could easily lead to mistakes where the loading state is confused with an empty response state.7 Replies
adverse-sapphire•3y ago
I was trying to figure out what exactly was your issue, so I made a little codesandbox: https://codesandbox.io/s/dependent-use-queries-0w0f48?file=/src/App.tsx
I'm still unclear as to what is your problem though. Could you try giving an example? (feel free to fork the codesandbox)
Sheraff
CodeSandbox
dependent-use-queries - CodeSandbox
dependent-use-queries by Sheraff using @tanstack/react-query, loader-utils, react, react-dom, react-scripts
inland-turquoise•3y ago
Same, I would probably need an example to understand more. The part I don't understand is:
Normally dependent queries would use the enabled option to specify whether or not the prerequisite data is ready to allow the query to run, but that's not an option at the top level for useQueriesFrom the useQueries doc page, looks like you would be able to pass a
enabled option to each query?
The useQueries hook accepts an options object with a queries key whose value is an array with query option objects identical to the useQuery hook
fascinating-indigoOP•3y ago
Thanks for the replies. The issue is when you don't have the data to even create the list of queries for
useQueries, for example, if you have an API endpoint that returns a list of post IDs, and another API endpoint to get the individual post, while the list of ids query is fetching you would not have any data to create the array of dependent queries, so there would be no individual queries yet to put the enabled option on.
The issue arises if you want to call both calls to useQuery and useQueries in the same component. In the sandbox they're split into 2 components which allows for there to be a conditional in the rendering logic which is not allowed for a single component under the rules of hooks. That solution does work, although I think it would some times be more convenient to have the option to have them both in the same component like you can with useQuery by using the enabled parameter.
Here's a code sandbox link demonstrating what I mean: https://codesandbox.io/s/dependent-use-queries-forked-j2shym?file=/src/App.tsx
In that fork I'm falling back to [] to allow it to run, but this means that the loading state needs to come from the productResults instead since the returned empty array does not distinguish between an empty list and a list that is still loading. That does work, but I don't think it's ideal because it makes it easier for mistakes to be made. My question isn't really how can you do it, but rather is there a better way to do it with the useQueries API as the current solution either makes it so you can't use useQueries at all by preventing the component from existing at all upstream, or you can use it but it gets put into a vague state.etler
CodeSandbox
dependent-use-queries (forked) - CodeSandbox
dependent-use-queries (forked) by etler using @tanstack/react-query, loader-utils, react, react-dom, react-scripts
inland-turquoise•3y ago
Got it. I'm not sure there is a better way. Personally, I would split the call into multiple components: I would fetch the product list at the top, then loop over the returned data to render one "Product" component per item and each of these "Product" component would contain a single
useQuery to fetch the details of that product.adverse-sapphire•3y ago
What you want it a single loading state that you don't have to repeat in several places or compute in a complicated way, and you don't want to split into components... That kinda sounds like Suspense to me. Not sure how this works with
useQueries though (are they executed in parallel or not).
It seems to work fine, and really allows you to go nuts with a waterfall of dependent queries! https://codesandbox.io/s/dependent-use-queries-with-suspense-bvvwgbadverse-sapphire•3y ago
No waterfall, all in parallel (except for the first one of course)

fascinating-indigoOP•3y ago
Our main use case is that sometimes we have a few chained queries that we use commonly that we have utility hooks that compose multiple dependent queries together, some of which are based around mapping queries so we need to use
useQueries. Since we want to re-use the logic in a utility hook, splitting it into multiple components would be cumbersome. In our previous sdk we had a useQueries hook that returned undefined when the dependent data was not yet defined, so this is one place where react-query was not compatible with our existing flow in our migration. Since the library doesn't have a way of communicating the dependent state natively for useQueries we're considering adding a wrapper hook around it to add an object wrapper that would communicate the dependent loading state while short circuiting the call to useQueries with an empty array.