Capítulo 12 de 80

Chapter 12: Query Functions

Core Idea

A queryFn is any function returning a Promise that resolves to non-undefined data or throws/rejects on failure; clients like fetch that don't throw on HTTP error status codes must be wrapped to throw manually, or the query will report success with an error-shaped body.

Key Concepts

  • undefined is an illegal success value: a query resolving to undefined is treated as failed — resolve null instead if you need to represent "nothing" as a successful result.
  • Error contract: the query is only considered errored if the queryFn throws or the returned Promise rejects — axios/graphql-request do this automatically for bad HTTP responses, but fetch does not, so check response.ok and throw yourself.
  • QueryFunctionContext: the single argument passed to every queryFnqueryKey, client (the QueryClient), signal (an AbortSignal for cancellation), meta (arbitrary metadata). Infinite queries additionally receive pageParam.
  • Extracting variables from the key: since queryKey is passed into the context, a queryFn can be a standalone function (not a closure) that destructures what it needs straight from queryKey — useful when you want to share the same fetcher across call sites.

Code Examples

// fetch doesn't throw on 4xx/5xx — you must
useQuery({
  queryKey: ['todos', todoId],
  queryFn: async () => {
    const response = await fetch('/todos/' + todoId)
    if (!response.ok) throw new Error('Network response was not ok')
    return response.json()
  },
})

// Standalone queryFn reading its args from QueryFunctionContext
function fetchTodoList({ queryKey }) {
  const [, { status, page }] = queryKey
  return fetch(`/todos?status=${status}&page=${page}`).then((r) => r.json())
}
useQuery({ queryKey: ['todos', { status, page }], queryFn: fetchTodoList })
  • What it demonstrates: manually throwing for fetch's non-throwing error contract, and a queryFn that reads its parameters from queryKey via QueryFunctionContext instead of closing over component variables.

Reference Tables

QueryFunctionContext fieldPurpose
queryKeyThe key this call is for
clientThe owning QueryClient
signalAbortSignal for cancellation
metaArbitrary metadata attached to the query
pageParam (infinite queries only)Current page's parameter

Key Takeaways

  1. Wrap non-throwing clients (fetch) to throw on bad responses — otherwise a 404 silently becomes a "successful" query with error-shaped data.
  2. Never resolve undefined on success; resolve null if there's genuinely nothing to represent.
  3. QueryFunctionContext.signal is the hook point for cancellation — wire it into fetch's own signal option to actually abort in-flight requests.

Connects To

  • Query Cancellation: uses the signal from this context.
  • Infinite Queries: the extra pageParam context field.