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
secondsky-claude-skills
219183 skills42 agents62 commands2 MCP
Install
$ npx -y skills add secondsky/claude-skills --skill tanstack-query --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/tanstack-query

Context preview

The summary Claude sees to decide when to auto-load this skill.

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

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
Ships withsecondsky-claude-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).

Get the whole plugin

Other skills on secondsky-claude-skills.