createQueryStore combines data fetching and state management in a single store. It replaces the React Query + Zustand dual-store pattern with reactive parameters and built-in caching.
Overview
createQueryStore provides:
- Automatic data fetching - Triggered by param changes
- Reactive parameters - Subscribe to other stores
- Smart caching - Per-query-key with configurable TTL
- Retry logic - Exponential backoff on errors
- Abort control - Cancel stale requests
- Background refetching - Keep data fresh
- Optional persistence - MMKV storage support
Basic Usage
In Components
Type Signatures
Config Object
Reactive Parameters
The most powerful feature is reactive params that auto-refetch when dependencies change:selectedAddress or chainId changes, the store automatically refetches with new params.
Signal Function $
The $ function subscribes to other stores:
Mixed Static and Reactive Params
Real-World Example
Here’s a production example from Rainbow’s perps feature:src/features/perps/stores/hlTradesStore.ts
Query State
The store exposes comprehensive query state:Cache Entry
Data Transformation
Transform fetched data before storing:Custom Data Setter
For complex state updates, usesetData:
Status Helpers
Manual Fetching
Fetch Options
Caching Behavior
Query Keys
Each unique set of params gets its own cache entry:Cache Pruning
Expired entries are automatically removed:- staleTime - When to refetch (data is “stale”)
- cacheTime - When to evict from cache (data is “expired”)
Keep Previous Data
Show old data while fetching new:Error Handling
Automatic Retry
Error State
Conditional Fetching
Disable fetching based on conditions:Persistence
Query stores can persist their cache:queryCache- Cached datalastFetchedAt- TimestampsqueryKey- Current keystatus- Query statuserror- Last error
enabled- Always reset to config value- Methods (
fetch,getData, etc.)
Advanced Patterns
Optimistic Updates
Dependent Queries
Parallel Fetching
Polling
Debugging
Best Practices
Set appropriate stale/cache times
Set appropriate stale/cache times
Balance freshness with performance:
Use reactive params for dynamic queries
Use reactive params for dynamic queries
Let the store handle refetching:
Handle errors gracefully
Handle errors gracefully
Always provide error handling:
Use AbortController for cancellation
Use AbortController for cancellation
The fetcher receives an AbortController:
Migration from React Query
Next Steps
createDerivedStore
Learn about derived/computed state
Storage System
Understand persistence