Skip to main content

QueryKeys

The QueryKeys class manages React Query keys and provides methods for cache operations like invalidation, refetching, and data retrieval. It's automatically created and used internally by QueryManager.

Key Generation

The QueryKeys class generates consistent query keys for different operations:

// Internal key structure
{
list: ['users', 'list'],
retrieve: (id) => ['users', 'retrieve', id],
create: ['users', 'create'],
update: ['users', 'update'],
delete: ['users', 'delete']
}

List Keys with Filters

List query keys automatically include filters when present:

// Without filters: ['users', 'list']
// With filters: ['users', 'list', { status: 'active', search: 'john' }]

const queryKey = queryKeys.listKeyWithFilters({ status: 'active' })
// Result: ['users', 'list', { status: 'active' }]

Cache Operations

Invalidation

// Access QueryKeys from QueryManager instance
const { queryKeys } = userQueryManager

// Invalidate all queries for this resource
await queryKeys.invalidateAll()

// Invalidate all list queries
await queryKeys.invalidateList()

// Invalidate list queries with specific filters
await queryKeys.invalidateList({ status: 'active' })

// Invalidate specific retrieve query
await queryKeys.invalidateRetrieve('user-123')

// Invalidate with options
await queryKeys.invalidateAll(
{ exact: true },
{ cancelRefetch: false }
)

Refetching

// Refetch all queries
await queryKeys.refetchAll()

// Refetch list queries
await queryKeys.refetchList()

// Refetch list queries with filters, ignoring specific query keys
await queryKeys.refetchList(
{ status: 'active' }, // filters
[['users', 'list', { status: 'inactive' }]] // ignore these keys
)

// Refetch specific retrieve query
await queryKeys.refetchRetrieve('user-123')

Data Retrieval

// Get list data from cache
const { items, itemMap } = queryKeys.getListData()
console.log('Cached users:', items)
console.log('User map:', itemMap['user-123'])

// Get list data with filters
const { items: activeUsers } = queryKeys.getListData({ status: 'active' })

// Get retrieve data from cache
const user = queryKeys.getRetrieveData('user-123')
console.log('Cached user:', user)

// Get retrieve data only from specific query (not from list cache)
const userFromQuery = queryKeys.getRetrieveData('user-123', true)

Query Management

// Cancel in-flight list queries
await queryKeys.cancelListQueries()

// Cancel specific list queries with filters
await queryKeys.cancelListQueries({ status: 'active' })

// Remove query data from cache
await queryKeys.removeRetrieveQueryData('user-123')

// Get all list queries
const listQueries = queryKeys.getAllListQueries()
console.log('Active list queries:', listQueries.length)

Practical Examples

Smart Cache Invalidation

function useUserActions() {
const { queryKeys } = userQueryManager

const handleUserStatusChange = async (userId: string) => {
// Invalidate the specific user
await queryKeys.invalidateRetrieve(userId)

// Invalidate all list queries since status affects filtering
await queryKeys.invalidateList()
}

const handleUserRoleChange = async (userId: string) => {
// Only invalidate lists that might be affected by role changes
await queryKeys.invalidateRetrieve(userId)
await queryKeys.invalidateList({ role: 'admin' })
await queryKeys.invalidateList({ role: 'user' })
}

return { handleUserStatusChange, handleUserRoleChange }
}

Background Refetching

function useBackgroundSync() {
const { queryKeys } = userQueryManager

useEffect(() => {
const interval = setInterval(async () => {
// Refetch stale data in background
await queryKeys.refetchAll(
{ type: 'active' }, // only active queries
{ cancelRefetch: false } // don't cancel ongoing requests
)
}, 5 * 60 * 1000) // every 5 minutes

return () => clearInterval(interval)
}, [])
}