1

I'm stuck with a situation where I am trying to use a RiverPod provider in my Flutter app to represent user preference data. In this case, the user preference data is stored in FireStore.

I'm stuck with understanding how to load provider state from Firestore. Currently, I'm trying to use the "userPreferencesFutureProvider" to load the 'GdUserPreferences" data from a service that calls Firestore, which then pushes the data into "userPreferencesProvider" using the 'overrideWith' method. However, when I access the user preference data via the 'userPreferencesProvider' provider the data loaded from Firestore is not present

final userPreferencesFutureProvider = FutureProvider<bool>( (ref) async {
  final p = ref.watch(userPrefsServiceProvider);
  GdUserPreferences? aPrefs = await p.load();
  if (aPrefs == null) {
    aPrefs =  GdUserPreferencesUtil.createDefault();
  }
  userPreferencesProvider.overrideWith((ref) => UserPreferencesNotifier(p,aPrefs!));
  return true;
});

final userPreferencesProvider = StateNotifierProvider<UserPreferencesNotifier,GdUserPreferences>((ref) {
  return UserPreferencesNotifier(ref.watch(userPrefsServiceProvider),GdUserPreferences());
});

Any suggestions?

Update

Further to the feedback received I have updated my code as shown below, but this still doesn't work...

final userPreferencesFutureProvider = FutureProvider<bool>( (ref) async {
  // get service that wraps calls to Firestore
  final p = ref.watch(userPrefsServiceProvider);
  // load data from Firestore
  GdUserPreferences? aPrefs = await p.load();
  // if none found then create default values
  if (aPrefs == null) {
    aPrefs =  GdUserPreferencesUtil.createDefault();
  }
  // push state into a provider that will be used
  ref.read(userPreferencesProvider.notifier).update(aPrefs);
  // this future returns a boolean as a way of indicating that the data load succeeded.
  // elsewhere in the app access to the user preference data is via the userPreferencesProvider
  return true;
});

final userPreferencesProvider = StateNotifierProvider<UserPreferencesNotifier,GdUserPreferences>((ref) {
  print('default provider');
  return UserPreferencesNotifier(ref.watch(userPrefsServiceProvider),GdUserPreferences());
});

class UserPreferencesNotifier extends StateNotifier<GdUserPreferences> {

  // service is a wrapper around FireStore collection call
  final GdUserPreferencesService service;

  UserPreferencesNotifier(this.service, super.state);

  void update(GdUserPreferences aNewPrefs) {
    print('update state');
    state = aNewPrefs;
  }

}

The purpose of having a separate FutureProvider and StateNotifierProvider, is that I can insert the FutureProvider when the app first loads. Then when I want to access the user preference data I can use the straight forward StateNotifierProvider, which avoids the complications of having Future Providers all over the app.

Note: using the print methods I can show that the 'update' method is called after the userPreferencesProvider is first created, so I can't understand why the data is not updated correctly

user2868835
  • 1,250
  • 3
  • 19
  • 33

1 Answers1

1

Apologies to all responders...

The problem was caused by a coding error on my side. I had two versions of 'userPreferencesProvider' defined in two different locations. Taking out the rogue duplicate definition and it now works fine.

user2868835
  • 1,250
  • 3
  • 19
  • 33