Capítulo 10 de 80
A query is a declarative subscription to async data identified by a unique queryKey; useQuery returns a result object whose status/boolean flags tell you exactly what to render, and a separate fetchStatus tells you whether the queryFn is actually running right now.
useQuery({ queryKey, queryFn }) — a unique key plus a function returning a Promise that resolves data or throws.status (about the data): 'pending' (no data yet) → 'error' (threw) → 'success' (data available). Mirrored as isPending/isError/isSuccess booleans.fetchStatus (about the queryFn, independent of status): 'fetching' (in flight), 'paused' (wants to fetch, blocked — see Network Mode), 'idle' (not doing anything). A query can be pending + paused simultaneously (first mount, no network) — checking isPending alone is not enough to safely show a spinner in that case.status answers "do we have data?"; fetchStatus answers "is the fetcher running?" — they combine independently (e.g. success + fetching during a background refetch).useMutation for anything that modifies server data.function Todos() {
const { isPending, isError, data, error } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
if (isPending) return <span>Loading...</span>
if (isError) return <span>Error: {error.message}</span>
// TypeScript narrows `data` to defined here
return <ul>{data.map((todo) => <li key={todo.id}>{todo.title}</li>)}</ul>
}
isPending then isError narrows data to non-undefined for TypeScript without a manual assertion.isPending, then isError, then treat data as available — this order is what gives you free TypeScript narrowing.status and fetchStatus — a pending query can be paused (offline) rather than actually fetching; isFetching is the flag for "actually in flight."status/isPending etc. and the raw status string are interchangeable — pick one style and stay consistent within a codebase.fetchStatus: 'paused'.queryFn must satisfy.