snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
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

This commit is contained in:
upstream-mirror
2026-09-16 01:13:08 +05:00
commit 3a013ccdfe
3570 changed files with 490194 additions and 0 deletions

View File

@@ -0,0 +1,145 @@
---
id: prefer-query-options
title: Prefer the use of queryOptions
---
Separating `queryKey` and `queryFn` can cause unexpected runtime issues when the same query key is accidentally used with more than one `queryFn`. Wrapping them in `queryOptions` (or `infiniteQueryOptions`) co-locates the key and function, making queries safer and easier to reuse.
## Rule Details
Examples of **incorrect** code for this rule:
```tsx
/* eslint "@tanstack/query/prefer-query-options": "error" */
function Component({ id }) {
const query = useQuery({
queryKey: ['get', id],
queryFn: () => Api.get(`/foo/${id}`),
})
// ...
}
```
```tsx
/* eslint "@tanstack/query/prefer-query-options": "error" */
function useFooQuery(id) {
return useQuery({
queryKey: ['get', id],
queryFn: () => Api.get(`/foo/${id}`),
})
}
```
Examples of **correct** code for this rule:
```tsx
/* eslint "@tanstack/query/prefer-query-options": "error" */
function getFooOptions(id) {
return queryOptions({
queryKey: ['get', id],
queryFn: () => Api.get(`/foo/${id}`),
})
}
function Component({ id }) {
const query = useQuery(getFooOptions(id))
// ...
}
```
```tsx
/* eslint "@tanstack/query/prefer-query-options": "error" */
function getFooOptions(id) {
return queryOptions({
queryKey: ['get', id],
queryFn: () => Api.get(`/foo/${id}`),
})
}
function useFooQuery(id) {
return useQuery({ ...getFooOptions(id), select: (data) => data.foo })
}
```
The rule also enforces reusing `queryKey` from a `queryOptions` result instead of typing it manually in `QueryClient` methods or filters.
Examples of **incorrect** `queryKey` references for this rule:
```tsx
/* eslint "@tanstack/query/prefer-query-options": "error" */
function todoOptions(id) {
return queryOptions({
queryKey: ['todo', id],
queryFn: () => api.getTodo(id),
})
}
function Component({ id }) {
const queryClient = useQueryClient()
return queryClient.getQueryData(['todo', id])
}
```
```tsx
/* eslint "@tanstack/query/prefer-query-options": "error" */
function todoOptions(id) {
return queryOptions({
queryKey: ['todo', id],
queryFn: () => api.getTodo(id),
})
}
function Component({ id }) {
const queryClient = useQueryClient()
return queryClient.invalidateQueries({ queryKey: ['todo', id] })
}
```
Examples of **correct** `queryKey` references for this rule:
```tsx
/* eslint "@tanstack/query/prefer-query-options": "error" */
function todoOptions(id) {
return queryOptions({
queryKey: ['todo', id],
queryFn: () => api.getTodo(id),
})
}
function Component({ id }) {
const queryClient = useQueryClient()
return queryClient.getQueryData(todoOptions(id).queryKey)
}
```
```tsx
/* eslint "@tanstack/query/prefer-query-options": "error" */
function todoOptions(id) {
return queryOptions({
queryKey: ['todo', id],
queryFn: () => api.getTodo(id),
})
}
function Component({ id }) {
const queryClient = useQueryClient()
return queryClient.invalidateQueries({ queryKey: todoOptions(id).queryKey })
}
```
## When Not To Use It
If you do not want to enforce the use of `queryOptions` in your codebase, you will not need this rule.
## Attributes
- [x] ✅ Recommended (strict)
- [ ] 🔧 Fixable