web/.agents/skills/tanstack-query-best-practices/rules/qk-array-structure.md
Query keys must always be arrays at the top level. This enables proper caching, invalidation matching, and query deduplication. Using non-array keys will cause unexpected behavior and cache misses.
// Never use strings or non-array types as query keys
const { data } = useQuery({
queryKey: 'todos', // Wrong: string instead of array
queryFn: fetchTodos,
})
const { data: user } = useQuery({
queryKey: { id: 1, type: 'user' }, // Wrong: object instead of array
queryFn: fetchUser,
})
// Always use arrays for query keys
const { data } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
})
const { data: user } = useQuery({
queryKey: ['user', 1],
queryFn: () => fetchUser(1),
})
// Complex keys with objects inside arrays are fine
const { data: filteredTodos } = useQuery({
queryKey: ['todos', { status: 'done', page: 1 }],
queryFn: () => fetchTodos({ status: 'done', page: 1 }),
})
invalidateQueries({ queryKey: ['todos'] }) matches all todo queries)['todos', 1] !== ['1', 'todos']