Skip to Content
DocumentationCore PackageAdvanced TopicsDependent Queries

Dependent Queries

Dependent queries are queries that should only execute after some other data is available.

Usage

Use the enabled option in QueryOptions to delay execution until a condition is met.

// 1. Fetch the User first final userQuery = QueryBuilder<User>( queryKey: 'user'.toQueryKey(), /* ... */ ); // 2. Fetch Posts *only* when User ID is available QueryBuilder<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...'); /* ... */ } )

API

OptionTypeDescription
enabledboolSet to false to prevent the query from fetching automatically. Defaults to true.

Examples

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

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)

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?

  • Detail Views: A “User Details” query should depend on the “Users List” query if logically nested.
  • Drill-downs: Order Items should depend on Order.
  • Resource ownership: If Query B makes no sense without Query A existing, link them.

Cancellation Behavior

  1. Parent Disposed: When the parent query hits 0 subscribers and its garbage collection timer expires.
  2. Cascade: The QueryClient detects the disposal and immediately runs .cancel() on all registered children.
  3. 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.
Last updated on