File: lukemorales-query-key-factory.md | Updated: 11/15/2025
Search...
+ K
Auto
Docs Examples GitHub Contributors
Docs Examples GitHub Contributors
Docs Examples GitHub Contributors
Docs Examples Github Contributors
Docs Examples Github Contributors
Docs Examples Github Contributors
Docs Examples Github Contributors
Docs Examples Github Contributors
Maintainers Partners Support Learn StatsBETA Discord Merch Blog GitHub Ethos Brand Guide
Documentation
Framework
React
Version
v4
Search...
+ K
Menu
Getting Started
Guides & Concepts
Community Resources
API Reference
ESLint
Plugins
Examples
Framework
React
Version
v4
Menu
Getting Started
Guides & Concepts
Community Resources
API Reference
ESLint
Plugins
Examples
On this page
Copy Markdown
Typesafe query key management with auto-completion features. Focus on writing and invalidating queries without the hassle of remembering how you've set up a key for a specific query!
You can install Query Key Factory via NPM .
bash
npm i @lukemorales/query-key-factory
npm i @lukemorales/query-key-factory
or
bash
pnpm add @lukemorales/query-key-factory
pnpm add @lukemorales/query-key-factory
or
bash
yarn add @lukemorales/query-key-factory
yarn add @lukemorales/query-key-factory
Start by defining the query keys for your app:
### Declare everything in a single file
tsx
import { createQueryKeyStore } from '@lukemorales/query-key-factory'
export const queryKeys = createQueryKeyStore({
users: null,
todos: {
detail: (todoId: string) => [todoId],
list: (filters: TodoFilters) => ({
queryKey: [{ filters }],
queryFn: (ctx) => api.getTodos({ filters, page: ctx.pageParam }),
}),
},
})
import { createQueryKeyStore } from '@lukemorales/query-key-factory'
export const queryKeys = createQueryKeyStore({
users: null,
todos: {
detail: (todoId: string) => [todoId],
list: (filters: TodoFilters) => ({
queryKey: [{ filters }],
queryFn: (ctx) => api.getTodos({ filters, page: ctx.pageParam }),
}),
},
})
### Fine-grained declaration by features
tsx
import { createQueryKeys, mergeQueryKeys } from '@lukemorales/query-key-factory'
// my-api/users.ts
export const usersKeys = createQueryKeys('users')
// my-api/todos.ts
export const todosKeys = createQueryKeys('todos', {
detail: (todoId: string) => [todoId],
list: (filters: TodoFilters) => ({
queryKey: [{ filters }],
queryFn: (ctx) => api.getTodos({ filters, page: ctx.pageParam }),
}),
})
// my-api/index.ts
export const queryKeys = mergeQueryKeys(usersKeys, todosKeys)
import { createQueryKeys, mergeQueryKeys } from '@lukemorales/query-key-factory'
// my-api/users.ts
export const usersKeys = createQueryKeys('users')
// my-api/todos.ts
export const todosKeys = createQueryKeys('todos', {
detail: (todoId: string) => [todoId],
list: (filters: TodoFilters) => ({
queryKey: [{ filters }],
queryFn: (ctx) => api.getTodos({ filters, page: ctx.pageParam }),
}),
})
// my-api/index.ts
export const queryKeys = mergeQueryKeys(usersKeys, todosKeys)
Use throughout your codebase as the single source for writing the query keys for your cache management:
tsx
import { queryKeys, completeTodo, fetchSingleTodo } from '../my-api'
export function Todo({ todoId }) {
const queryClient = useQueryClient()
const query = useQuery(queryKeys.todos.detail(todoId))
const mutation = useMutation({
mutationFn: completeTodo,
onSuccess: () => {
// Invalidate and refetch
queryClient.invalidateQueries({ queryKey: queryKeys.todos.list.queryKey })
},
})
return (
<div>
<h1>
{query.data?.title}
</h1>
<p>
{query.data?.description}
</p>
<button
onClick={() => {
mutation.mutate({ todoId })
}}
>
Complete Todo
</button>
</div>
)
}
import { queryKeys, completeTodo, fetchSingleTodo } from '../my-api'
export function Todo({ todoId }) {
const queryClient = useQueryClient()
const query = useQuery(queryKeys.todos.detail(todoId))
const mutation = useMutation({
mutationFn: completeTodo,
onSuccess: () => {
// Invalidate and refetch
queryClient.invalidateQueries({ queryKey: queryKeys.todos.list.queryKey })
},
})
return (
<div>
<h1>
{query.data?.title}
</h1>
<p>
{query.data?.description}
</p>
<button
onClick={() => {
mutation.mutate({ todoId })
}}
>
Complete Todo
</button>
</div>
)
}
Check the complete documentation on GitHub .
[###### Want to Skip the Docs?
Query.gg - The Official React Query Course
\
“If you’re serious about *really* understanding React Query, there’s no better way than with query.gg”—Tanner Linsley
Learn More](https://query.gg/?s=tanstack)
You are currently reading v4 docs. Redirect to latest version?
Latest Hide
