T
TanStack3y ago
unwilling-turquoise

Combine/Transform result of multiple queries

I’m trying to create a hook that combines the data from 2 endpoints. I was able to transform the incoming data of a single query using select. What I really need is the data of 2 parallal queries combined tho. I was trying to use the select function for this purpose like below, but i'm not sure this is the best way of going about it. Also, this way hook useC only returns the data, without any of the query information like loading or errors.
const useC = () => {
const [c, setC] = useState();

const {data: dataA} = useQuery({
queryKey: [...],
queryFn: fetchA,
select: data => {
if (dataB) {
setC(combineIntoC({a: data, b: dataB))
}
}
});

const {data: dataB} = useQuery({
queryKey: [...],
queryFn: fetchB,
select: data => {
if (dataA) {
setC(combineIntoC({a: dataA, b: data))
}
}
});

return c
}
const useC = () => {
const [c, setC] = useState();

const {data: dataA} = useQuery({
queryKey: [...],
queryFn: fetchA,
select: data => {
if (dataB) {
setC(combineIntoC({a: data, b: dataB))
}
}
});

const {data: dataB} = useQuery({
queryKey: [...],
queryFn: fetchB,
select: data => {
if (dataA) {
setC(combineIntoC({a: dataA, b: data))
}
}
});

return c
}
I hope this example makes it clear what the goal is. (Note, if there is a better way to merge the result of 2 parallel queries, please let me know 🙂 I might not be looking in the right direction for my problem.) Thanks in advance
8 Replies
automatic-azure
automatic-azure3y ago
Hi, one way could be to perform the merge in the queryFn - define keys and queryFn for A - define keys and queryFn for B This way you could still call them individually (and benefit from cache) - define keys and queryFn for C and in queryFnC you could do something like
const [dataA, dataB] = await Promise.all([queryClient.fetchQuery(keysA), queryClient.fetchQuery(keysB)])
// Merge…
return mergedData
const [dataA, dataB] = await Promise.all([queryClient.fetchQuery(keysA), queryClient.fetchQuery(keysB)])
// Merge…
return mergedData
Note: you might have to define a staleTime while performing fetchQuery to benefit from the cache. This can also be done using queryDefaults As an example, we set up a codesandbox with this pattern some times ago (RQ v3 etc.) but it could give you a better understanding of this pattern.
unwilling-turquoise
unwilling-turquoiseOP3y ago
Thank you so much! The codesandbox is really helpful, in my mind the queryFn always had to fetch from an API, I didn't realise you could also do something like this. Thanks!
automatic-azure
automatic-azure3y ago
Great.
automatic-azure
automatic-azure3y ago
You can use React Query for slow computation, not just API | Swizec...
You can use the ergonomics of React Query for any slow operation and it's wonderful.
automatic-azure
automatic-azure3y ago
react-query lets you wrap any async calls, not just API ones. And thus it allows you to have a unique way of dealing with loading, error etc. states
unwilling-turquoise
unwilling-turquoiseOP3y ago
Thanks! I'll give it a read! I do have an additional question about the Codesandbox you shared, because is it possible to 'forward' the isLoading/isFetching flag from both queries, where if either of the queries is loading/fetching, the 'PostWithUser' query also displays as loading? Or does it have that behaviour already? (Didn't test it yet)
automatic-azure
automatic-azure3y ago
Should not be needed. The isLoading of PostWithUser would be true until the queryFn is finished. So this means when both queryA and queryB are done.

Did you find this page helpful?