Core Dependent Queries
Dependent queries are queries that should only execute after some other data is available.
Use the enabled option in QueryOptions to delay execution until a condition is met.
// 1. Fetch the User firstfinal userQuery = QueryBuilder<User>( queryKey: 'user'.toQueryKey(), /* ... */);
// 2. Fetch Posts *only* when User ID is availableQueryBuilder<List<Post>>( // Key depends on user ID queryKey: 'posts:${userQuery.state.data?.id}'.toQueryKey(), queryFn: () => api.fetchPosts(userQuery.state.data!.id),
// Disable until we have the ID options: QueryOptions( enabled: userQuery.state.hasData, // <--- The magic switch ), builder: (context, state) { if (state.isIdle) return Text('Waiting for user...'); /* ... */ })| Option | Type | Description |
|---|---|---|
enabled | bool | Set to false to prevent the query from fetching automatically. Defaults to true. |
Examples
Section titled “Examples”Serial Fetching
Section titled “Serial Fetching”Sometimes you need to chain requests A -> B -> C.
// This pattern typically involves nesting QueryBuilders// or using the result of one query to drive the next.
QueryBuilder<User>( queryKey: 'user'.toQueryKey(), builder: (context, userState) { if (!userState.hasData) return Loading();
return QueryBuilder<List<Project>>( // Dependent key queryKey: 'projects:${userState.data.id}'.toQueryKey(), queryFn: () => fetchProjects(userState.data.id), // Only run when user is loaded (redundant if nested, but good practice) options: QueryOptions(enabled: userState.hasData), builder: (context, projectState) { // ... } ); })Waiting for User Input
Section titled “Waiting for User Input”Don’t search until the user types something.
QueryBuilder( queryKey: 'search:$searchTerm'.toQueryKey(), queryFn: () => searchApi(searchTerm), options: QueryOptions( enabled: searchTerm.isNotEmpty, // Only fetch if text exists ), /* ... */)Lifecycle Dependencies (Cascading Cancellation)
Section titled “Lifecycle Dependencies (Cascading Cancellation)”While enabled controls when a query starts, the dependsOn parameter controls when a query stops.
Use dependsOn to link a child query to a parent query. If the parent query is disposed (removed from memory), the child query is automatically cancelled. This prevents orphan requests from consuming resources when their conceptual “owner” is gone.
// Parent Query (e.g., User Profile)final userKey = 'user:123'.toQueryKey();final userQuery = client.getQuery(userKey, /* ... */);
// Child Query (e.g., User Posts)client.getQuery( 'user:123:posts'.toQueryKey(), queryFn: () => api.fetchUserPosts(123), // 🔗 Link to parent dependsOn: userKey,);When to use dependsOn?
Section titled “When to use dependsOn?”- Detail Views: A “User Details” query should depend on the “Users List” query if logically nested.
- Drill-downs:
Order Itemsshould depend onOrder. - Resource ownership: If
Query Bmakes no sense withoutQuery Aexisting, link them.
Cancellation Behavior
Section titled “Cancellation Behavior”- Parent Disposed: When the parent query hits 0 subscribers and its garbage collection timer expires.
- Cascade: The
QueryClientdetects the disposal and immediately runs.cancel()on all registered children. - Effect: Any in-flight network requests for the children are aborted. The children are not removed from cache immediately (they follow their own GC logic), but their fetching is stopped.