82 lines
1.9 KiB
Markdown
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.
|