Skip to content

Riverpod Query Prefetching

Prefetching allows you to fetch data before it’s actually needed in the UI, warming up the cache and making navigation feel instantaneous. The Riverpod adapter provides a convenient way to do this via extensions on WidgetRef.

The fasq_riverpod package adds prefetchQuery and prefetchQueries methods to Riverpod’s WidgetRef.

class CategoryList extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return ListView(
children: categories.map((category) {
return MouseRegion(
onEnter: (_) {
// Prefetch category details when user hovers over the tile
ref.prefetchQuery(
CategoryKeys.detail(category.id),
() => api.fetchCategoryDetail(category.id),
);
},
child: ListTile(
title: Text(category.name),
onTap: () => Navigator.push(...),
),
);
}).toList(),
);
}
}

As shown above, prefetching when a user hovers over a link or button is a highly effective way to hide network latency. By the time the user clicks, the data might already be in the cache.

If you know a user is very likely to navigate to a specific screen, you can prefetch the required data in the onTap handler before pushing the route.

onTap: () async {
// Start prefetching
ref.prefetchQuery(
QueryKeys.userProfile(userId),
() => api.fetchProfile(userId),
);
// Navigate immediately
context.push('/profile/$userId');
}

You can prefetch multiple queries at once using prefetchQueries:

onEnter: (_) {
ref.prefetchQueries([
PrefetchConfig(
queryKey: QueryKeys.user(id),
queryFn: () => api.fetchUser(id),
),
PrefetchConfig(
queryKey: QueryKeys.userPosts(id),
queryFn: () => api.fetchUserPosts(id),
),
]);
}
  1. Cache Check: prefetchQuery first checks if the cache already contains fresh data for the given key.
  2. Background Fetch: If the data is missing or stale, it triggers a fetch in the background.
  3. Non-blocking: Prefetching does not block the UI or change the state of your existing ref.watch providers until the fetch completes.
  4. Shared Cache: Because it uses the same QueryClient as your providers, the fetched data is immediately available to any widget that watches that query key.