Capítulo 15 de 80

Chapter 15: Parallel Queries

Core Idea

A fixed number of parallel queries needs no special API — just call useQuery side by side; a dynamic number (changing per render) requires useQueries instead, since calling a variable number of hooks would break the Rules of Hooks.

Key Concepts

  • Manual parallel queries: any number of useQuery/useInfiniteQuery calls placed side by side in a component execute in parallel automatically — no extra wiring needed.
  • Suspense caveat: this manual pattern breaks under Suspense, because the first query throws a promise and suspends the component before the others even run. Use useSuspenseQueries (recommended) or split each into its own component instead.
  • Dynamic parallel queries (useQueries): takes { queries: [...] }, an array of query-config objects built at render time (e.g. via .map), and returns an array of results in the same order — the escape hatch for "N queries, N determined by data."
  • TypeScript limitation with inline select: an inline select inside a useQueries query object can't infer its argument from that same object's queryFn (falls back to unknown) — annotate select's parameter explicitly, or build the query with queryOptions instead.

Code Examples

// Fixed count — plain useQuery calls, run in parallel
const usersQuery = useQuery({ queryKey: ['users'], queryFn: fetchUsers })
const teamsQuery = useQuery({ queryKey: ['teams'], queryFn: fetchTeams })

// Dynamic count — useQueries
function App({ users }) {
  const userQueries = useQueries({
    queries: users.map((user) => ({
      queryKey: ['user', user.id],
      queryFn: () => fetchUserById(user.id),
    })),
  })
}
  • What it demonstrates: the two shapes of parallelism — static side-by-side hooks vs. a data-driven array passed to useQueries.

Key Takeaways

  1. Don't reach for useQueries when the query count is fixed — plain useQuery calls are simpler and already run in parallel.
  2. Under Suspense, manual side-by-side queries serialize instead of parallelizing — use useSuspenseQueries for a dynamic set, or separate components for a fixed set.
  3. Annotate select's parameter type explicitly inside useQueries query objects, or use queryOptions, to avoid silently losing type inference.

Connects To

  • Suspense: why manual parallelism breaks under it, and the useSuspenseQueries fix.
  • Dependent Queries: useQueries combined with a prior query's result to build the dynamic list.