# Tanstack Query Intent Core Fetch And Observe Queries

> Use this when reading server state with useQuery, useQueries, createQuery, injectQuery, QueryObserver, QueryClient.fetchQuery, ensureQueryData, status, fetchStatus, pending, paused, success, and error states.

- Skill: `lukasa1993/tanstack-query-intent-core-fetch-and-observe-queries` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add lukasa1993/tanstack-query-intent-core-fetch-and-observe-queries`
- Raw SKILL.md: https://api.skillmd.com/api/skills/lukasa1993/tanstack-query-intent-core-fetch-and-observe-queries/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: lukasa1993 (https://skillmd.com/u/lukasa1993)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/lukasa1993/tanstack-query-intent-core-fetch-and-observe-queries

---


## Setup

```tsx
import { useQuery } from '@tanstack/react-query'

export function Todos() {
  const query = useQuery({
    queryKey: ['todos'],
    queryFn: async () => [{ id: 1, title: 'Ship' }],
  })

  if (query.isPending) return <p>Loading</p>
  if (query.isError) return <p>{query.error.message}</p>
  return <pre>{JSON.stringify(query.data)}</pre>
}
```

## Core Patterns

### Fetch imperatively through QueryClient

```ts
import { QueryClient } from '@tanstack/react-query'

const queryClient = new QueryClient()

export function loadTodo(todoId: string) {
  return queryClient.fetchQuery({
    queryKey: ['todo', todoId],
    queryFn: async () => ({ id: todoId }),
  })
}
```

### Ensure cached data for loaders

```ts
import { QueryClient } from '@tanstack/react-query'

const queryClient = new QueryClient()

export function ensureTodos() {
  return queryClient.ensureQueryData({
    queryKey: ['todos'],
    queryFn: async () => [{ id: 1 }],
  })
}
```

### Distinguish status from fetchStatus

```tsx
import { useQuery } from '@tanstack/react-query'

export function TodoCount() {
  const query = useQuery({
    queryKey: ['todos'],
    queryFn: async () => [{ id: 1 }],
  })
  const label =
    query.fetchStatus === 'fetching' && query.status === 'success'
      ? 'Refreshing'
      : 'Ready'
  return (
    <p>
      {query.data?.length ?? 0} {label}
    </p>
  )
}
```

## Common Mistakes

### CRITICAL Void query function

Wrong:

```ts
import { useQuery } from '@tanstack/react-query'

export function useTodos() {
  return useQuery({
    queryKey: ['todos'],
    queryFn: async () => {
      await Promise.resolve([{ id: 1 }])
    },
  })
}
```

Correct:

```ts
import { useQuery } from '@tanstack/react-query'

export function useTodos() {
  return useQuery({
    queryKey: ['todos'],
    queryFn: async () => Promise.resolve([{ id: 1 }]),
  })
}
```

Query functions must return data; a missing return caches `undefined`.

Source: TanStack/query:docs/eslint/no-void-query-fn.md

### HIGH Only checking pending offline

Wrong:

```tsx
import { useQuery } from '@tanstack/react-query'

export function Todos() {
  const query = useQuery({
    queryKey: ['todos'],
    queryFn: async () => [{ id: 1 }],
    networkMode: 'online',
  })
  return query.isPending ? <p>Loading</p> : <p>{query.fetchStatus}</p>
}
```

Correct:

```tsx
import { useQuery } from '@tanstack/react-query'

export function Todos() {
  const query = useQuery({
    queryKey: ['todos'],
    queryFn: async () => [{ id: 1 }],
    networkMode: 'online',
  })
  return query.fetchStatus === 'paused' ? <p>Offline</p> : <p>{query.status}</p>
}
```

`status` describes data state; `fetchStatus` describes whether fetching is paused, fetching, or idle.

Source: TanStack/query:docs/framework/react/guides/queries.md

### HIGH Using queries for writes

Wrong:

```ts
import { useQuery } from '@tanstack/react-query'

export function useSaveTodo(title: string) {
  return useQuery({
    queryKey: ['saveTodo', title],
    queryFn: async () => ({ id: 1, title }),
  })
}
```

Correct:

```ts
import { useMutation } from '@tanstack/react-query'

export function useSaveTodo() {
  return useMutation({
    mutationFn: async (title: string) => ({ id: 1, title }),
  })
}
```

Queries are for reads; writes need mutation lifecycle hooks, invalidation, rollback, and mutation state.

Source: TanStack/query:docs/framework/react/guides/mutations.md

See also: `core/tune-defaults-freshness-retries-and-refetching` for how defaults change status behavior.

