RiverPod – How to await using FutureProvider on AsyncValue not in widget

Issue

I need to get 1 field 1 time from Firebase Cloud Firestore. How do I accomplish this with providers outside of Widget build?

Below are my combined providers. appStartupProvider is a FutureProvider and I want to get the bool value from this 1 field in firestore. However, the await in appStartupProvider states "’await’ applied to ‘AsyncValue’, which is not a ‘Future’".

final accountStreamProvider = StreamProvider<Account>((ref) {
  final database = ref.watch(databaseProvider);
  return database != null ? database.accountStream() : const Stream.empty();
});

final _accountSetupCompleteProvider = Provider<AsyncValue<bool>>((ref) {
  return ref
      .watch(accountStreamProvider)
      .whenData((account) => account?.accountSetupComplete ?? false);
});

final appStartupProvider = FutureProvider<bool>((ref) async {
  final accountSetupComplete = await ref.watch(_accountSetupCompleteProvider);

  return accountSetupComplete;
});

Obviously missing some key knowledge here on combing providers and AsyncValue, but I’m trying to accomplish the situation stated on RiverPod Combining Providers page, where I see await is being used.

enter image description here

Solution

The example in the documentation was incorrect at the time of your post. It has since been updated and is now correct.

This is how you could write it:

final accountStreamProvider = StreamProvider<Account?>((ref) {
  final database = ref.watch(databaseProvider);
  return database != null ? database.accountStream() : const Stream.empty();
});

final _accountSetupCompleteProvider = FutureProvider<bool>((ref) async {
  final account = await ref.watch(accountStreamProvider.last);
  return account?.accountSetupComplete ?? false;
});

final appStartupProvider = FutureProvider<bool>((ref) async {
  final accountSetupComplete = await ref.watch(_accountSetupCompleteProvider.future);
  return accountSetupComplete;
});

Or:

final accountStreamProvider = StreamProvider<Account?>((ref) {
  final database = ref.watch(databaseProvider);
  return database != null ? database.accountStream() : const Stream.empty();
});

final _accountSetupCompleteProvider = Provider<AsyncValue<bool>>((ref) {
  return ref
      .watch(accountStreamProvider)
      .whenData((account) => account?.accountSetupComplete ?? false);
});

final appStartupProvider = Provider<bool>((ref) {
  final accountSetupComplete = ref.watch(_accountSetupCompleteProvider).maybeWhen(
        data: (data) => data, 
        orElse: () => false,
      );

  return accountSetupComplete;
});

Answered By – Alex Hartford

Answer Checked By – Cary Denson (FlutterFixes Admin)

Leave a Reply

Your email address will not be published.