T
TanStack3mo ago
ambitious-aqua

[BEST PRACTICE] - Interdependent queries in the page loader function

Hi guys ! 👋 I'm wondering what is the best way to fetch multiple data, using TanStack Query, in the page loader function ? Note that almost every request i need, depends on the result of the request n-1 I would do something like :
loader: async () => {
const res1 = await queryClient.ensureQueryData(...options)
const res2 = await queryClient.ensureQueryData(...options + res1)
const res3 = await queryClient.ensureQueryData(...options + res2)
return {res1, res2, res3}
})
loader: async () => {
const res1 = await queryClient.ensureQueryData(...options)
const res2 = await queryClient.ensureQueryData(...options + res1)
const res3 = await queryClient.ensureQueryData(...options + res2)
return {res1, res2, res3}
})
But it feels wrong 😅 It might be a misconception of how my API is made and the data is returned 🤷‍♂️
7 Replies
fascinating-indigo
fascinating-indigo3mo ago
If res2 request depends on the result of res1, and res3 depends on the result of rs2 then you will need the waterfall. Most commonly the queries are not dependent of one another, so you can await Promise.all([res1, res2]).
ambitious-aqua
ambitious-aquaOP3mo ago
okay i see, seems logical
optimistic-gold
optimistic-gold3mo ago
Do you actually use the queries separately? Because if not, you could also just wrap them inside one queryFn and treat them as one "unit" e.g.
function getMyQueryOptions() {
return queryOptions({
queryKey: ['myQuery'],
queryFn: async () => {
const res1 = await fetch('/api/one');
const res2 = await fetch(`/api/two?id=${res1.id}`);
const res3 = await fetch(`/api/three?id=${res2.id}`);
return { res1, res2, res3 };
}
})
}
function getMyQueryOptions() {
return queryOptions({
queryKey: ['myQuery'],
queryFn: async () => {
const res1 = await fetch('/api/one');
const res2 = await fetch(`/api/two?id=${res1.id}`);
const res3 = await fetch(`/api/three?id=${res2.id}`);
return { res1, res2, res3 };
}
})
}
loader: async () => {
return queryClient.ensureQueryData(getMyQueryOptions())
}
loader: async () => {
return queryClient.ensureQueryData(getMyQueryOptions())
}
fascinating-indigo
fascinating-indigo3mo ago
what would be the benefit of this approach?
optimistic-gold
optimistic-gold3mo ago
Easier to reuse, complexity is hidden behind the queryOptions helper easier to invalidate cache, only need 1 key depends on the use-case really. If you will always use the queries together it definitely makes sense to do
fascinating-indigo
fascinating-indigo3mo ago
you would lose other benefits though, like request dedup, etc.
optimistic-gold
optimistic-gold3mo ago
They will still dedupe as long as they use the same queryFn/key. If you do use the queries individually then yeah it doesn't make much sense as you'll cache the data twice

Did you find this page helpful?