Riverpod Query Metadata
Metadata allows you to attach extra information to your queries and mutations. This is extremely powerful when combined with global observers to handle side effects like showing snackbars, logging, or triggering analytics consistently across your entire app.
Adding Metadata to Providers
Section titled “Adding Metadata to Providers”Both queryProvider and mutationProvider accept a meta property within their options.
Query Metadata
Section titled “Query Metadata”Use QueryMeta to store info about a data fetch:
final usersProvider = queryProvider<List<User>>( 'users'.toQueryKey(), () => api.fetchUsers(), options: QueryOptions( meta: const QueryMeta( errorMessage: 'Failed to load users. Please check your connection.', ), ),);Mutation Metadata
Section titled “Mutation Metadata”Use MutationMeta to store info about an update:
final createUserProvider = mutationProvider<User, String>( (name) => api.createUser(name), options: MutationOptions( meta: const MutationMeta( successMessage: 'User created successfully!', errorMessage: 'Could not create user.', invalidateKeys: [['users']], ), ),);Consuming Metadata Globally
Section titled “Consuming Metadata Globally”The real power of metadata comes from consuming it in a global observer. This allows you to write the logic for showing snackbars or alerts once and have it work for every query/mutation in your app.
1. Create a Global Observer
Section titled “1. Create a Global Observer”class FeedbackObserver extends FasqObserver { @override void onMutationSuccess(MutationSnapshot snapshot, MutationMeta? meta, BuildContext? context) { if (meta?.successMessage != null && context != null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(meta!.successMessage!)), ); } }
@override void onQueryError(QuerySnapshot snapshot, QueryMeta? meta, BuildContext? context) { if (meta?.errorMessage != null && context != null) { showGlobalErrorDialog(context, meta!.errorMessage!); } }}2. Register the Observer
Section titled “2. Register the Observer”Override the fasqObserversProvider at the root of your app:
void main() { runApp( ProviderScope( overrides: [ fasqObserversProvider.overrideWithValue([ FeedbackObserver(), FasqLogger(), ]), ], child: const MyApp(), ), );}Why use Metadata?
Section titled “Why use Metadata?”- Separation of Concerns: Your UI widgets don’t need to know about snackbars or error dialogs. They just watch the provider.
- Consistency: All error messages and success alerts look and behave the same way throughout the app.
- Declarative: Side effects are declared alongside the provider definition, making the intent clear.
Next Steps
Section titled “Next Steps”- Configuration - Learn more about global observer setup
- Security Features - How metadata is handled for secure queries
- Examples - See metadata in a real-world app