1. Centralize Key Definitions
Create a single file for all your query keys:
typescript
// src/lib/queryKeys.ts
import { createKeyFactory } from 'awesome-key-factory';
export const queryKeys = createKeyFactory('app', {
// ... all your keys
});Then import where needed:
typescript
import { queryKeys } from '@/lib/queryKeys';2. Use Descriptive Names
typescript
// ✅ Good
const keys = createKeyFactory('app', {
users: {
detail: (params: { id: string }) => [params.id],
},
});
// ❌ Bad
const keys = createKeyFactory('a', {
u: {
d: (p: { i: string }) => [p.i],
},
});3. Group Related Keys
Organize keys by domain or feature:
typescript
const queryKeys = createKeyFactory('app', {
// Authentication
auth: {
currentUser: () => [],
session: () => [],
},
// User management
users: {
all: () => [],
detail: (params: { id: string }) => [params.id],
},
// Posts
posts: {
all: () => [],
detail: (params: { id: string }) => [params.id],
},
});4. Use Array Shorthand for Static Keys
When keys don't need parameters, use array shorthand:
typescript
// ✅ Good - array shorthand
const keys = createKeyFactory('app', {
users: {
all: [],
},
});
// Also good - function with empty params
const keys = createKeyFactory('app', {
users: {
all: () => [],
},
});5. Leverage Intermediate Level Access
Use intermediate levels for query invalidation:
typescript
// Invalidate all user-related queries
queryClient.invalidateQueries({
queryKey: queryKeys.users(),
});
// Invalidate all post-related queries
queryClient.invalidateQueries({
queryKey: queryKeys.posts(),
});6. Keep Keys Consistent
Maintain consistent naming and structure:
typescript
// ✅ Consistent pattern
const queryKeys = createKeyFactory('app', {
users: {
all: () => [],
detail: (params: { id: string }) => [params.id],
list: (params: { page: number }) => [params.page.toString()],
},
posts: {
all: () => [],
detail: (params: { id: string }) => [params.id],
list: (params: { page: number }) => [params.page.toString()],
},
});