1

I'm new to riverpod, and I want to check that I am doing things correct.

I have a screen on my Flutter app where the use inputs lots of information about a session. Like start time, end time, notes, duration, date etc etc. All this data in the end is stored in a dart complex object MySession(), will all the above properties.

My question is, in the meantime, I am creating a seerate provider for each field. Like this:

final selectedDateProvider = StateProvider((ref) => DateTime.now());
final sessionDurationMinutesProvider = StateProvider<int>((ref) => 0);

Now in the class, I call the providers like this in the build method:

selectedDate = ref.watch(selectedDateProvider);
sessionDurationMinutes = ref.watch(sessionDurationMinutesProvider);

Then I display them in the widgets.

When they are editing, I save the state like this:

ref.read(selectedDateProvider.notifier).state = datePick;

My question is, I have lots and lots of fields on this page. So I have to create lots of providers for each field. Is this the correct practise? Can I not make a customclass for all these fields, and then make one provider which will return this custom class?

On the riverpod docs it says: You should not use StateProvider if: your state is a complex object (such as a custom class, a list/map, ...) https://riverpod.dev/docs/providers/state_provider

I hope its clear!

Thanks

RJB
  • 1,704
  • 23
  • 50

2 Answers2

0

You already answered your question ;)

Yes, you can.

Make a class that will store the state of all the input fields and expose it through StateProvider.

To do it effectively you will probably need a copyWith method which can be written manually or generated. One of the possible approaches is to use freezed.

mfkw1
  • 920
  • 6
  • 15
  • On the riverpod docs it says: You should not use StateProvider if: your state is a complex object (such as a custom class, a list/map, ...) – RJB Jul 07 '22 at 09:47
  • Please link the docs – mfkw1 Jul 07 '22 at 09:59
  • Linked in the answer – RJB Jul 07 '22 at 10:48
  • I think that author meant "complex object that can mutate in unpredictable ways". Creating immutable "data class" and storing it in StateProvider should be totally fine. – mfkw1 Jul 07 '22 at 12:31
  • Hi, thanks. But this still isn't working like this. Please look here, https://stackoverflow.com/questions/72897709/flutter-riverpod-stateprovider-not-uploading-ui? – RJB Jul 07 '22 at 18:55
  • This is because your class is not immutable. Also, you should follow-up in your current question, not open a new one. – mfkw1 Jul 08 '22 at 11:19
0

You can define a single provider, and then use select to 'select' a single field. For example:

final configProvider = StreamProvider<Configuration>(...);

final productsProvider = FutureProvider<List<Product>>((ref) async {
final host = await ref.watch(configProvider.selectAsync((config) =>     config.host));

return dio.get('$host/products');    
})

In this example ( from here: https://riverpod.dev/docs/concepts/combining_providers )

You can listen only to a single field: in this manner you will minimize the number of refreshes because if the use changes a part of the state not 'selected' in your code, your page would not refreshed.

In your case I would make only a single provider with all fields, then in every part of your UI I would use select/selectAsync to load the single field. Moreover, because your are at first steps on Riverpod, I suggest you to see riverpod_generator: this package introduces a new 'language': you will create your providers using annotations @riverpod, take a look at the docs, it deserves to be used. (https://pub.dev/packages/riverpod_generator)

Mike
  • 335
  • 1
  • 8