Skip to content
Development
Skill

/tanstack-query

TanStack Query v5 (React Query) server state management. Use for data fetching, caching, mutations, or encountering v4 migration, stale data, invalidation errors.

From plugin
claude-skills
241183 skills42 agents62 commands2 MCP

Claude Code

$ npx -y skills add secondsky/claude-skills --skill tanstack-query --agent claude-code

SKILL.md

tanstack-query.SKILL.md
name: tanstack-query
description: "TanStack Query v5 (React Query) server state management. Use for data fetching, caching, mutations, or encountering v4 migration, stale data, invalidation errors."

metadata:
  keywords:
    - TanStack Query
    - React Query
    - useQuery
    - useMutation
    - useInfiniteQuery
    - useSuspenseQuery
    - QueryClient
    - QueryClientProvider
    - data fetching
    - server state
    - caching
    - staleTime
    - gcTime
    - query invalidation
    - prefetching
    - optimistic updates
    - mutations
    - query keys
    - query functions
    - error boundaries
    - suspense
    - React Query DevTools
    - v5 migration
    - v4 to v5
    - request waterfalls
    - background refetching
    - cacheTime renamed
    - loading status renamed
    - pending status
    - initialPageParam required
    - keepPreviousData removed
    - placeholderData
    - query callbacks removed
    - onSuccess removed
    - onError removed
    - object syntax required

license: MIT

TanStack Query (React Query) v5

**Status**: Production Ready ✅ **Last Updated**: 2026-08-03 **Dependencies**: React 18.0+ (18.3+ recommended), TypeScript 4.9+ (5.x preferred) **Latest Versions**: @tanstack/react-query@5.101.4, @tanstack/react-query-devtools@5.101.4, @tanstack/eslint-plugin-query@5.101.4

---

Quick Start (5 Minutes)

1. Install Dependencies

# choose your package manager
pnpm add @tanstack/react-query@latest @tanstack/react-query-devtools@latest
# or
npm install @tanstack/react-query@latest @tanstack/react-query-devtools@latest
# or
bun add @tanstack/react-query@latest @tanstack/react-query-devtools@latest

**Why this matters:**

  • TanStack Query v5 requires React 18+ (uses useSyncExternalStore)
  • DevTools are essential for debugging queries and mutations
  • v5 has breaking changes from v4 - use latest for all fixes

2. Set Up QueryClient Provider

// src/main.tsx or src/index.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import App from './App'

// Create a client
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 1000 * 60 * 5, // 5 minutes
      gcTime: 1000 * 60 * 60, // 1 hour (formerly cacheTime)
      retry: 1,
      refetchOnWindowFocus: false,
    },
  },
})

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <QueryClientProvider client={queryClient}>
      <App />
      <ReactQueryDevtools initialIsOpen={false} />
    </QueryClientProvider>
  </StrictMode>
)

**CRITICAL:**

  • Wrap entire app with `QueryClientProvider`
  • Configure `staleTime` to avoid excessive refetches (default is 0)
  • Use `gcTime` (not `cacheTime` - renamed in v5)
  • DevTools should be inside provider

**Know the defaults (v5):**

  • `staleTime: 0` → data is immediately stale, so refetches on mount/focus unless you raise it
  • `gcTime: 5 * 60 * 1000` → inactive data is garbage-collected after 5 minutes
  • `retry: 3` in browsers, `retry: 0` on the server
  • `refetchOnWindowFocus: true` and `refetchOnReconnect: true`
  • `networkMode: 'online'` (requests pause while offline). Switch to `'always'` for SSR/prefetch where you don't want cancellation. citeturn1search0turn1search1

3. Create First Query

// src/hooks/useTodos.ts
import { useQuery } from '@tanstack/react-query'

type Todo = {
  id: number
  title: string
  completed: boolean
}

async function fetchTodos(): Promise<Todo[]> {
  const response = await fetch('/api/todos')
  if (!response.ok) {
    throw new Error('Failed to fetch todos')
  }
  return response.json()
}

export function useTodos() {
  return useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodos,
  })
}

// Usage in component:
function TodoList() {
  const { data, isPending, isError, error } = useTodos()

  if (isPending) return <div>Loading...</div>
  if (isError) return <div>Error: {error.message}</div>

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

**CRITICAL:**

  • v5 requires object syntax: `useQuery({ queryKey, queryFn })`
  • Use `isPending` (not `isLoading` - that now means "pending AND fetching")
  • Always throw errors in queryFn for proper error handling
  • QueryKey should be array for consistent cache keys

4. Create First Mutation

// src/hooks/useAddTodo.ts
import { useMutation, useQueryClient } from '@tanstack/react-query'

type NewTodo = {
  title: string
}

async function addTodo(newTodo: NewTodo) {
  const response = await fetch('/api/todos', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(newTodo),
  })
  if (!response.ok) throw new Error('Failed to add todo')
  return response.json()
}

export function useAddTodo() {
  const queryClient = useQueryClient()

  return useMutation({
    mutationFn: addTodo,
    onSuccess: () => {
      // Invalidate and refetch todos
      queryClient.invalidateQueries({ queryKey: ['todos'] })
    },
  })
}

// Usage in component:
function AddTodoForm() {
  const { mutate, isPending } = useAddTodo()

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault()
    const formData = new FormData(e.currentTarget)
    mutate({ title: formData.get('title') as string })
  }

  return (
    <form onSubmit={handleSubmit}>
      <input name="title" required />
      <button type="submit" disabled={isPending}>
        {isPending ? 'Adding...' : 'Add Todo'}
      </button>
    </form>
  )
}

**Why this works:**

  • Mutations use callbacks (`onSuccess`, `onError`, `onSettled`) - queries don't
  • `invalidateQueries` triggers background refetch
  • Mutations don't cache by default (correct behavior)

---

The 7-Step Setup Process

Step 1: Install Dependencies

# Core library (requ
Read more
@secondsky
Ships withclaude-skills

145 production-ready skills for Claude Code CLI 🔌 Platform / Harness Support These plugins ship as Claude Code marketplace plugins (.claude-plugin/ manifests) and Codex CLI plugins (.codex-plugin/ manifests).

241183 skills42 agents2 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
241
Star history of secondsky/claude-skills on GitHub, a chart by star-history.com

Other skills on claude-skills.

aceternity-ui

aceternity-ui

100+ animated React components (Aceternity UI) for Next.js with Tailwind. Use for hero sections, parallax, 3D effects, or…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills11d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about tanstack-query.

Which coding agents can use tanstack-query?
tanstack-query installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.