← marketplace
engineerslibrarysha:14954140544ec8femanual

tanstack-query

Use when managing server state in a frontend app: fetching, caching, background refetching, and synchronizing async data without writing manual loading logic.

Install confidence
curl --create-dirs -fsSL https://skillmake.xyz/i/tanstack-query -o ~/.claude/skills/tanstack-query/SKILL.md
Pinned content
sha:14954140544ec8fe
Generated with
manual
Source
tanstack.com

The file served at /api/marketplace/tanstack-query-14954140/raw matches this hash. Inspect before install, then copy the command.

5,571 chars · ~1,393 tokens
---
name: tanstack-query
description: "Use when managing server state in a frontend app: fetching, caching, background refetching, and synchronizing async data without writing manual loading logic."
source: https://tanstack.com/query/latest/docs/framework/react/overview
generated: 2026-07-02T18:43:37.726Z
category: library
audience: engineers
---

## When to use

- Fetching and caching server data in React, Vue, Svelte, Solid, or Angular apps
- Eliminating manual loading/error/refetch boilerplate around async data
- Keeping UI in sync with the server via background refetch and cache invalidation
- Implementing optimistic updates, pagination, or infinite scroll over a query cache

## Key concepts

### Query keys

An array that uniquely identifies cached data, e.g. ['todos', id]. The key drives caching, refetching, and invalidation; changing any part triggers a new fetch.

### staleTime vs gcTime

staleTime is how long data is considered fresh (no auto-refetch); gcTime (formerly cacheTime) is how long inactive/unused data stays in cache before garbage collection. Default staleTime is 0, gcTime is 5 minutes.

### QueryClient and provider

A single QueryClient holds the cache. Wrap the app in QueryClientProvider so hooks can access it. Defaults can be set via defaultOptions.

### Mutations

useMutation handles create/update/delete. Pair onSuccess/onSettled with queryClient.invalidateQueries to refetch affected data, or perform optimistic updates with onMutate.

### Invalidation

queryClient.invalidateQueries({ queryKey }) marks matching queries stale and refetches active ones, the canonical way to reflect server changes after a mutation.

### Status flags

Queries expose status (pending/error/success) plus fetchStatus (fetching/idle), isPending, isError, isFetching, and data. isFetching is true on background refetches even when data exists.

## API reference

```
new QueryClient(options) + <QueryClientProvider client={...}>
```

Create the cache and provide it to the component tree.

```
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient({
  defaultOptions: { queries: { staleTime: 60_000 } },
});
export function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Todos />
    </QueryClientProvider>
  );
}
```

```
useQuery({ queryKey, queryFn, ...options })
```

Read async data; returns data, error, isPending, isError, refetch, and more.

```
import { useQuery } from '@tanstack/react-query';
function Todos() {
  const { data, isPending, isError } = useQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('/api/todos').then((r) => r.json()),
  });
  if (isPending) return <p>Loading</p>;
  if (isError) return <p>Error</p>;
  return <ul>{data.map((t) => <li key={t.id}>{t.title}</li>)}</ul>;
}
```

```
useMutation({ mutationFn, onSuccess, onMutate })
```

Perform writes and react to their lifecycle; call mutate/mutateAsync to trigger.

```
import { useMutation, useQueryClient } from '@tanstack/react-query';
function AddTodo() {
  const qc = useQueryClient();
  const m = useMutation({
    mutationFn: (title) => fetch('/api/todos', { method: 'POST', body: title }),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['todos'] }),
  });
  return <button onClick={() => m.mutate('new')}>Add</button>;
}
```

```
useInfiniteQuery({ queryKey, queryFn, getNextPageParam, initialPageParam })
```

Cursor/page based infinite loading; exposes fetchNextPage and hasNextPage.

```
const q = useInfiniteQuery({
  queryKey: ['feed'],
  queryFn: ({ pageParam }) => fetchPage(pageParam),
  initialPageParam: 0,
  getNextPageParam: (last) => last.nextCursor,
});
```

```
queryClient.invalidateQueries({ queryKey })
```

Mark matching queries stale and refetch active ones.

```
queryClient.invalidateQueries({ queryKey: ['todos'] });
```

```
queryClient.setQueryData(queryKey, updater)
```

Write data directly into the cache, e.g. for optimistic updates.

```
queryClient.setQueryData(['todos'], (old) => [...old, newTodo]);
```

```
queryClient.prefetchQuery({ queryKey, queryFn })
```

Warm the cache before a component renders, e.g. on hover or server-side.

```
await queryClient.prefetchQuery({ queryKey: ['todo', id], queryFn: () => getTodo(id) });
```

```
useQueryClient()
```

Access the QueryClient from within components to invalidate, set, or prefetch.

```
const queryClient = useQueryClient();
```

## Gotchas

- Default staleTime is 0, so queries refetch on mount, window focus, and reconnect; raise staleTime to reduce refetches.
- queryFn must throw/reject on failure for isError to trigger; fetch() does not reject on HTTP 4xx/5xx, so check response.ok.
- Object query keys are matched structurally and order-sensitively; key serialization is deterministic so put stable values in.
- cacheTime was renamed gcTime in v5; v5 also replaced isLoading semantics with isPending for the no-data state.
- isFetching is true during background refetches even when data is present; use isPending for the initial no-data load.
- Optimistic updates via onMutate need a rollback in onError and a final reconcile in onSettled (invalidate or refetch).
- Each useQuery call with the same key shares one cache entry; do not expect independent per-component fetches.
- In React 18 strict mode and SSR, create the QueryClient inside a stable ref/useState, not on every render.

---
Generated by SkillMake from https://tanstack.com/query/latest/docs/framework/react/overview on 2026-07-02T18:43:37.726Z.
Verify against source before relying on details.

File: ~/.claude/skills/tanstack-query/SKILL.md