Core Concepts
Understanding the fundamental concepts of Fasq will help you build better applications and avoid common pitfalls.
Queries
Section titled “Queries”A query is a declarative dependency on an asynchronous data source. Queries are tied to a unique QueryKey and can be used to fetch, cache, and synchronize data.
Query Lifecycle
Section titled “Query Lifecycle”- Idle: Query hasn’t started yet.
- Loading: Initial fetch is in progress.
- Success: Data is available.
- Error: Fetch failed.
Query Keys
Section titled “Query Keys”Fasq uses QueryKey to identify cache entries. The simplest way to create one is using the .toQueryKey() extension on strings.
// Simple key'users'.toQueryKey()
// Parameterized key (using string interpolation)'user:$userId'.toQueryKey()
// Hierarchical key'posts:user:$userId:page:$page'.toQueryKey()Typed Query Keys
Section titled “Typed Query Keys”For type safety, you can use TypedQueryKey.
// Strongly typed key for List<User>const usersKey = TypedQueryKey<List<User>>('users');Mutations
Section titled “Mutations”Mutations are for creating, updating, or deleting data. Unlike queries:
- They are active only when triggered (via
mutate()). - They do not auto-refetch.
- They are one-off operations.
MutationBuilder<User, String>( mutationFn: (name) => api.createUser(name), builder: (context, state, mutate) { return ElevatedButton( onPressed: () => mutate('New Name'), child: Text('Create'), ); },)Caching & Staleness
Section titled “Caching & Staleness”Fasq implements a Stale-While-Revalidate strategy.
1. Stale Time
Section titled “1. Stale Time”The duration data is considered “fresh”.
- If data is fresh, Fasq returns it from cache without a network request.
- If data is stale, Fasq returns it from cache immediately, but triggers a background refetch.
- Default:
Duration.zero(always stale).
2. Cache Time
Section titled “2. Cache Time”The duration inactive data remains in memory.
- If a query is unmounted (e.g., user leaves the screen), the data sits in cache for this duration.
- If accessed again within this time, it’s reused.
- If not accessed, it is garbage collected.
- Default:
5 minutes.
QueryOptions( staleTime: Duration(minutes: 5), // Trust cache for 5 minutes cacheTime: Duration(minutes: 30), // Keep in memory for 30 minutes)Request Deduplication
Section titled “Request Deduplication”If multiple widgets request the same queryKey at the same time, Fasq sends only one network request. Once the request completes, all widgets update with the data simultaneously.
// Widget AQueryBuilder(queryKey: 'data'.toQueryKey(), ...)
// Widget B (same key)QueryBuilder(queryKey: 'data'.toQueryKey(), ...)
// -> 1 Fetch only!Global State
Section titled “Global State”The QueryClient acts as the single source of truth. It holds the cache and manages all active queries.
// Access globallyfinal client = QueryClient();
// Invalidate specific dataclient.invalidateQuery('users'.toQueryKey());
// Prefetch dataclient.prefetchQuery('profile'.toQueryKey(), fetchProfile);