Docs
CodeRabbit
Cloudflare
Railway
WorkOS
Clerk
SerpAPI
Netlify
OpenRouter
AG Grid
Sentry
Prisma
Electric
Unkey
CodeRabbit
Cloudflare
Railway
WorkOS
Clerk
SerpAPI
Netlify
OpenRouter
AG Grid
Sentry
Prisma
Electric
Unkey

Server-state manager

TanStackQuery

Stop syncing server data by hand.

Query gives async data a cache, a lifecycle, and a set of declarative APIs for fetching, sharing, refetching, mutating, and observing server state across TypeScript applications.

Total DownloadsWeekly DownloadsGitHub Stars

The server-state standard for modern frontend apps.

Read the docs

Server-state cache

freshness, retries, gc, dedupe

Mutation workflow

optimistic UI, rollback, invalidate

Framework adapters

React, Vue, Solid, Svelte, Angular, Lit

query client
fetchingrev 0 / primed

['issues', 'router-cache']

Router dashboard

p98
3 observers

['issues', 'project-detail']

Project detail

p91
2 observers

['issues', 'offline-queue']

Offline mutation queue

p84
1 observers

useQuery()

Components declare the data they need. The cache coordinates fetches, subscribers, freshness, and background updates.

status: success
isFetching: true
staleTime: 3_200
mutation: idle

Why Query

Server state is not the same problem as client state.

Server data is remote, shared, cached, refetched, invalidated, and sometimes stale on purpose. Query handles that lifecycle directly instead of making you recreate it with reducers, effects, and synchronized stores.

Important defaults do the boring work.

Caching, request dedupe, retries, background refetching, window-focus updates, and garbage collection are already wired for the shape of real apps.

Query keys become the cache contract.

Keys describe the resource, inputs, filters, and scope so reads, writes, invalidation, prefetching, and devtools all speak the same language.

Mutations have a real lifecycle.

Handle pending UI, optimistic writes, invalidation, rollback, and follow-up refetches without inventing an ad hoc client-state machine.

Devtools make the cache visible.

See query keys, observers, freshness, retries, errors, mutations, and cache contents while the app is actually running.

1

Fetch

A query function resolves data or throws. Query owns retry, cancellation, and deduping.

2

Share

Every observer reads the same cache entry instead of refetching from every component.

3

Revalidate

Stale data can stay on screen while a background refetch quietly refreshes it.

4

Collect

Unused data sticks around long enough to feel instant, then garbage collection cleans up.

queryKey: ['projects', filters]
queryFn: fetchProjects
staleTime: 30_000
gcTime: 300_000

Cache lifecycle

Keep data useful while the network catches up.

Query lets stale data remain valuable. Screens can render instantly from cache, refetch in the background, keep previous results during pagination, and recover when the user comes back online.

Mutations

Writes update the world, then the cache.

Query keeps mutation work explicit: optimistic updates, pending states, error recovery, invalidation, and background reconciliation are first-class instead of scattered through components.

1optimistic write

setQueryData(['todos'], next)

2server mutation

await saveTodo(todo)

3targeted refresh

invalidateQueries(['todos'])

4rollback path

onError: restoreSnapshot

Result: the UI can feel instant, the server remains the source of truth, and the cache knows exactly what changed.

Framework adapters

One server-state model, every UI runtime.

The core cache model travels across frameworks. Teams can keep the same query keys, invalidation strategy, mutation semantics, and mental model whether the UI is React, Vue, Solid, Svelte, Angular, Preact, or Lit.

ReactVueSolidSvelteAngularPreactLit
Just a quick look...
import { useQuery } from '@tanstack/react-query'

function Todos() {
  const { data, isPending, error } = useQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('/api/todos').then(r => r.json()),
  })

  if (isPending) return <span>Loading...</span>
  if (error) return <span>Oops!</span>

  return <ul>{data.map(t => <li key={t.id}>{t.title}</li>)}</ul>
}

export default Todos
import { useQuery } from '@tanstack/react-query'

function Todos() {
  const { data, isPending, error } = useQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('/api/todos').then(r => r.json()),
  })

  if (isPending) return <span>Loading...</span>
  if (error) return <span>Oops!</span>

  return <ul>{data.map(t => <li key={t.id}>{t.title}</li>)}</ul>
}

export default Todos

Field notes

Query is the default answer for async server state.

The original copy was right: Query saves code by deleting whole categories of hand-written fetching, loading, retry, cache, and mutation logic.

Loved by Developers

See what teams are saying

"Honestly, if React Query had been around before Redux, I don't think Redux would have been nearly as popular as it was."

Kent C. Dodds
@kentcdodds · Epic Web

"If I could go back in time and mass myself... I would hand myself a flash drive with a copy of react-query on it."

Kent C. Dodds
@kentcdodds · Epic Web

"React Query won. There's no denying that."

Theo Browne
@t3dotgg · Ping Labs

"TanStack Query has been a game-changer for us. We love using it for react-admin."

react-admin
@ReactAdmin · Marmelab

"The more I use React + Vite + TanStack Router + TypeScript + TanStack Query, the more I love it."

Catalin Pit
@catalinmpit · Developer Advocate

"Combined with React Query, this stack has been a game-changer for my productivity."

Dominik (TkDodo)
@TkDodo · TanStack

"Honestly, if React Query had been around before Redux, I don't think Redux would have been nearly as popular as it was."

Kent C. Dodds
@kentcdodds · Epic Web

"If I could go back in time and mass myself... I would hand myself a flash drive with a copy of react-query on it."

Kent C. Dodds
@kentcdodds · Epic Web

"React Query won. There's no denying that."

Theo Browne
@t3dotgg · Ping Labs

"TanStack Query has been a game-changer for us. We love using it for react-admin."

react-admin
@ReactAdmin · Marmelab

"The more I use React + Vite + TanStack Router + TypeScript + TanStack Query, the more I love it."

Catalin Pit
@catalinmpit · Developer Advocate

"Combined with React Query, this stack has been a game-changer for my productivity."

Dominik (TkDodo)
@TkDodo · TanStack

Open source ecosystem

Maintainers, education, sponsors, and partners keep Query moving.

Query is built in public and taught in public. The maintainers, partner integrations, Query.gg, and GitHub sponsors all stay close to the product story.

GitHub Sponsors

Wow, you've come a long way!
Only one thing left to do...