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.
PrefetchExtension
Section titled “PrefetchExtension”The fasq_riverpod package adds prefetchQuery and prefetchQueries methods to Riverpod’s WidgetRef.
Basic Prefetching
Section titled “Basic Prefetching”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(), ); }}When to Prefetch
Section titled “When to Prefetch”On Hover
Section titled “On Hover”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.
Before Navigation
Section titled “Before Navigation”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');}Multiple Queries
Section titled “Multiple Queries”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), ), ]);}How it Works
Section titled “How it Works”- Cache Check:
prefetchQueryfirst checks if the cache already contains fresh data for the given key. - Background Fetch: If the data is missing or stale, it triggers a fetch in the background.
- Non-blocking: Prefetching does not block the UI or change the state of your existing
ref.watchproviders until the fetch completes. - Shared Cache: Because it uses the same
QueryClientas your providers, the fetched data is immediately available to any widget that watches that query key.
Next Steps
Section titled “Next Steps”queryProvider- How to consume prefetched datainfiniteQueryProvider- Prefetching paginated lists- Caching Strategy - Understanding how long prefetched data stays fresh