Files
upstream-mirror 3a013ccdfe
Some checks failed
autofix.ci / autofix (push) Failing after 4s
Release / Release (push) Has been skipped
GitHub Actions Security Analysis / Run zizmor (push) Failing after 2s
snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
2026-09-16 01:13:08 +05:00

82 lines
1.9 KiB
Markdown

---
id: query-functions
title: Query Functions
---
A query function can be any function that returns a promise. The promise should resolve data or throw an error.
```ts
createQueryController(this, {
queryKey: ['todos'],
queryFn: fetchTodos,
})
createQueryController(this, () => ({
queryKey: ['todo', this.todoId],
queryFn: () => fetchTodo(this.todoId),
}))
```
## Handling Errors
TanStack Query needs failed query functions to throw or return a rejected promise. Some clients do that automatically. The browser `fetch` API does not, so check `response.ok` yourself:
```ts
async function fetchTodos(): Promise<Todo[]> {
const response = await fetch('/api/todos')
if (!response.ok) {
throw new Error('Failed to fetch todos')
}
return response.json() as Promise<Todo[]>
}
```
The thrown error is available on the query result:
```ts
const query = this.todos()
if (query.isError) {
return html`Error: ${query.error.message}`
}
```
## Query Function Context
TanStack Query passes a context object to every query function. It includes:
- `queryKey`: the current query key
- `client`: the `QueryClient`
- `signal`: an `AbortSignal` for cancellation
- `meta`: optional query metadata
```ts
createQueryController(this, {
queryKey: ['todos', { status: 'open' }],
queryFn: async ({ queryKey, signal }) => {
const [, filters] = queryKey
const response = await fetch(`/api/todos?status=${filters.status}`, {
signal,
})
if (!response.ok) throw new Error('Failed to fetch todos')
return response.json() as Promise<Todo[]>
},
})
```
Infinite query functions also receive `pageParam`:
```ts
createInfiniteQueryController(this, {
queryKey: ['projects'],
queryFn: ({ pageParam }) => fetchProjectsPage(pageParam),
initialPageParam: 1,
getNextPageParam: (lastPage) =>
lastPage.hasMore ? lastPage.page + 1 : undefined,
})
```
See [Infinite Queries](./infinite-queries.md) for the controller-specific behavior.