home / skills / deckardger / tanstack-agent-skills / tanstack-query

tanstack-query skill

/skills/tanstack-query

This skill helps you implement TanStack Query best practices for data fetching, caching, mutations, and SSR in React applications.

npx playbooks add skill deckardger/tanstack-agent-skills --skill tanstack-query

Review the files below or copy the command above to add this skill to your agents.

Files (22)
SKILL.md
4.8 KB
---
name: tanstack-query-best-practices
description: TanStack Query (React Query) best practices for data fetching, caching, mutations, and server state management. Activate when building data-driven React applications with server state.
---

# TanStack Query Best Practices

Comprehensive guidelines for implementing TanStack Query (React Query) patterns in React applications. These rules optimize data fetching, caching, mutations, and server state synchronization.

## When to Apply

- Creating new data fetching logic
- Setting up query configurations
- Implementing mutations and optimistic updates
- Configuring caching strategies
- Integrating with SSR/SSG
- Refactoring existing data fetching code

## Rule Categories by Priority

| Priority | Category | Rules | Impact |
|----------|----------|-------|--------|
| CRITICAL | Query Keys | 5 rules | Prevents cache bugs and data inconsistencies |
| CRITICAL | Caching | 5 rules | Optimizes performance and data freshness |
| HIGH | Mutations | 6 rules | Ensures data integrity and UI consistency |
| HIGH | Error Handling | 3 rules | Prevents poor user experiences |
| MEDIUM | Prefetching | 4 rules | Improves perceived performance |
| MEDIUM | Parallel Queries | 2 rules | Enables dynamic parallel fetching |
| MEDIUM | Infinite Queries | 3 rules | Prevents pagination bugs |
| MEDIUM | SSR Integration | 4 rules | Enables proper hydration |
| LOW | Performance | 4 rules | Reduces unnecessary re-renders |
| LOW | Offline Support | 2 rules | Enables offline-first patterns |

## Quick Reference

### Query Keys (Prefix: `qk-`)

- `qk-array-structure` — Always use arrays for query keys
- `qk-include-dependencies` — Include all variables the query depends on
- `qk-hierarchical-organization` — Organize keys hierarchically (entity → id → filters)
- `qk-factory-pattern` — Use query key factories for complex applications
- `qk-serializable` — Ensure all key parts are JSON-serializable

### Caching (Prefix: `cache-`)

- `cache-stale-time` — Set appropriate staleTime based on data volatility
- `cache-gc-time` — Configure gcTime for inactive query retention
- `cache-defaults` — Set sensible defaults at QueryClient level
- `cache-invalidation` — Use targeted invalidation over broad patterns
- `cache-placeholder-vs-initial` — Understand placeholder vs initial data differences

### Mutations (Prefix: `mut-`)

- `mut-invalidate-queries` — Always invalidate related queries after mutations
- `mut-optimistic-updates` — Implement optimistic updates for responsive UI
- `mut-rollback-context` — Provide rollback context from onMutate
- `mut-error-handling` — Handle mutation errors gracefully
- `mut-loading-states` — Use isPending for mutation loading states
- `mut-mutation-state` — Use useMutationState for cross-component tracking

### Error Handling (Prefix: `err-`)

- `err-error-boundaries` — Use error boundaries with useQueryErrorResetBoundary
- `err-retry-config` — Configure retry logic appropriately
- `err-fallback-data` — Provide fallback data when appropriate

### Prefetching (Prefix: `pf-`)

- `pf-intent-prefetch` — Prefetch on user intent (hover, focus)
- `pf-route-prefetch` — Prefetch data during route transitions
- `pf-stale-time-config` — Set staleTime when prefetching
- `pf-ensure-query-data` — Use ensureQueryData for conditional prefetching

### Infinite Queries (Prefix: `inf-`)

- `inf-page-params` — Always provide getNextPageParam
- `inf-loading-guards` — Check isFetchingNextPage before fetching more
- `inf-max-pages` — Consider maxPages for large datasets

### SSR Integration (Prefix: `ssr-`)

- `ssr-dehydration` — Use dehydrate/hydrate pattern for SSR
- `ssr-client-per-request` — Create QueryClient per request
- `ssr-stale-time-server` — Set higher staleTime on server
- `ssr-hydration-boundary` — Wrap with HydrationBoundary

### Parallel Queries (Prefix: `parallel-`)

- `parallel-use-queries` — Use useQueries for dynamic parallel queries
- `query-cancellation` — Implement query cancellation properly

### Performance (Prefix: `perf-`)

- `perf-select-transform` — Use select to transform/filter data
- `perf-structural-sharing` — Leverage structural sharing
- `perf-notify-change-props` — Limit re-renders with notifyOnChangeProps
- `perf-placeholder-data` — Use placeholderData for instant UI

### Offline Support (Prefix: `offline-`)

- `network-mode` — Configure network mode for offline support
- `persist-queries` — Configure query persistence for offline support

## How to Use

Each rule file in the `rules/` directory contains:
1. **Explanation** — Why this pattern matters
2. **Bad Example** — Anti-pattern to avoid
3. **Good Example** — Recommended implementation
4. **Context** — When to apply or skip this rule

## Full Reference

See individual rule files in `rules/` directory for detailed guidance and code examples.

Overview

This skill captures battle-tested best practices for using TanStack Query (React Query) in data-driven React applications. It focuses on robust query key design, caching, mutations, SSR hydration, and performance patterns to reduce bugs and improve UX. Use it to standardize server-state logic and make data flows predictable across your app.

How this skill works

The skill inspects common patterns and anti-patterns and presents concise rules grouped by priority: Query Keys, Caching, Mutations, Error Handling, Prefetching, SSR, and performance. Each rule includes an explanation, a bad example, a good example, and context for when to apply or skip it. Apply these rules while authoring or refactoring data fetching code to enforce consistency and prevent cache-related bugs.

When to use it

  • When designing new data fetching and caching layers for React apps
  • While implementing or refactoring mutations and optimistic updates
  • During SSR/SSG integration and hydration work
  • When configuring global QueryClient defaults and caching strategies
  • When diagnosing stale data, cache inconsistencies, or slow UX

Best practices

  • Always build query keys as arrays and include every dependent variable to avoid cache collisions
  • Set sensible staleTime and gcTime at QueryClient level; prefer targeted invalidation over broad purges
  • Invalidate related queries and provide rollback context in onMutate for safe optimistic updates
  • Use dehydrate/hydrate and a per-request QueryClient for SSR; increase server staleTime and wrap with HydrationBoundary
  • Leverage select, structural sharing, and notifyOnChangeProps to minimize re-renders and transform data cheaply

Example use cases

  • Creating a list/detail UI with hierarchical query keys: ['users', userId, { include }]
  • Implementing optimistic update for a create/edit mutation with rollback on error
  • Prefetching route data on hover and ensuring staleTime is set for preloaded queries
  • Hydrating server-fetched queries during SSG/SSR to eliminate loading flashes
  • Using useQueries for dynamic parallel fetches and cancelling unused requests

FAQ

How do I choose staleTime?

Base staleTime on data volatility and UX needs: longer for rarely changing data, shorter for real-time feeds. Use server-side longer staleTime during SSR to reduce refetches on hydration.

When should I use optimistic updates?

Use optimistic updates for actions where immediate UI feedback matters (e.g., likes, counters). Always provide rollback context and robust error handling to restore consistent state on failure.