TanStackT
TanStack3mo ago
4 replies
brilliant-lime

Calling dependent queries declaratively and imperatively

Hi, is there any good way to be able to call dependent queries both via hooks and imperatively? For independent queries, it's great that you can do this
const projectsOpts = (userId: string) => ({
  queryKey: ['user', userId, 'projects'],
  queryFn: () => fetchProjects(userId),
})

useQuery(projectsOpts('123'))
useSuspenseQuery(projectsOpts('123'))
queryClient.fetchQuery(projectsOpts('123'))

but for dependent queries, I end up having to write it three times
const collaboratorsOpts = (projectId: string) => ({
  queryKey: ['project', projectId, 'collaborators'],
  queryFn: () => fetchCollaborators(projectId),
})

// Hook version
function useAllCollaborators(userId: string) {
  const {data: projects} = useQuery(projectsOpts(userId))
  return useQueries({
    queries: projects?.map(p => collaboratorsOpts(p.id)),
  })
}

// Suspense hook
function useAllCollaboratorsSuspense(userId: string) {
  const {data: projects} = useSuspenseQuery(projectsOpts(userId))
  return useSuspenseQueries({
    queries: projects.map(p => collaboratorsOpts(p.id)),
  })
}

// Imperative version
async function fetchAllCollaborators(
  qc: QueryClient,
  userId: string,
) {
  const projects = await qc.fetchQuery(projectsOpts(userId))
  return await Promise.all(
    projects.map(p =>
      qc.fetchQuery(collaboratorsOpts(p.id))
    )
  )
}
Was this page helpful?