Advanced Features
Custom Effect Hook
const usersManager = new QueryManager<User>({
// ... configurations
useListEffect: (listQuery) => {
// Custom implementation for refresh
useQueryListRefresh(listQuery, {
staleTime: 5000 // 5 seconds
})
// Or custom logic
useEffect(() => {
const interval = setInterval(() => {
listQuery.refreshQuery(true) // silent refresh
}, 30000) // every 30 seconds
return () => clearInterval(interval)
}, [])
},
})
CodeleapQueryClient - Advanced Methods
Creating Basic Queries
// Simple query
const profileQuery = queryClient.queryKey(['profile'], {
queryFn: async () => {
const response = await api.get('/profile/')
return response.data
},
})
// Using in component
function Profile() {
const { data, isLoading } = useQuery({
queryKey: profileQuery.key,
})
const handleRefresh = async () => {
const newData = await profileQuery.refresh()
console.log('Updated data:', newData)
}
return (
<div>
{isLoading ? 'Loading...' : data?.name}
<button onClick={handleRefresh}>Refresh</button>
</div>
)
}
Query Polling
Polling allows you to execute a query repeatedly until a stop condition:
const startPolling = async () => {
const results = await profileQuery.poll<string[]>({
interval: 2000, // 2 seconds
leading: false, // Don't execute immediately
initialData: [], // Initial data
async callback(query, count, previousResults) {
const currentName = query.state.data?.name
const allNames = [...(previousResults || []), currentName]
console.log(`Iteration ${count}:`, allNames)
// Stop condition
return {
stop: count >= 5 || currentName?.includes('admin'),
data: allNames,
}
},
})
console.log('Final polling result:', results)
}
Change Listeners
const removeListener = profileQuery.listen((event) => {
if (event.type === 'updated') {
console.log('Profile updated:', event.query.state.data)
}
})
// Remove listener when no longer needed
// removeListener()
Dynamic Query Keys
For queries that depend on parameters:
// Defining dynamic key builder
const userQueryBuilder = (userId: number) => ['user', userId]
// Creating dynamic proxy
const userQueries = queryClient.dynamicQueryKey<User, [number]>(
userQueryBuilder
)
// Using
const handleGetUser = async (userId: number) => {
const user = await userQueries.ensureData(userId)
console.log('User:', user)
// Refreshing specific user
const refreshedUser = await userQueries.refresh(userId)
// Polling specific user
const pollResults = await userQueries.poll(userId, {
interval: 1000,
callback: async (query, count) => ({
stop: count > 3,
data: query.state.data,
}),
})
}
Advanced Configurations
Configuration Options
const manager = new QueryManager<Item>({
name: 'items',
itemType: {} as Item,
queryClient: client,
// Optional configurations
limit: 25, // Default per page
generateId: () => Date.now(), // Custom ID generator
keyExtractor: (item) => item.slug, // Custom key extractor
// Default configurations for operations
creation: {
optimistic: true,
appendTo: 'start',
},
update: {
optimistic: true,
},
deletion: {
optimistic: false, // Safer for deletions
},
// Initial metadata
initialMeta: {
category: 'default',
permissions: ['read'],
},
})
TanStack Query Integration
The library is fully compatible with TanStack Query. You can use both simultaneously:
// Using TanStack Query directly
const { data } = useQuery({
queryKey: ['custom-query'],
queryFn: () => api.get('/custom-endpoint/'),
})
// Using Codeleap manager
const { items } = manager.useList()
// Accessing underlying QueryClient
const queryClient = manager.queryClient
queryClient.invalidateQueries(['custom-query'])