简体   繁体   中英

Riverpod watch multiple providers of the same type and return latest value

I have a question regarding riverpod library and its possibilities.

What I want to achieve is to have one provider that emits latest value from three different providers. I can easily do this with StreamGroup.merge([stream1, stream2, sream3]) but I am thinking if there is other way just by using multiple ref.watch() and return last emitted value.

I saw that in Provider there is a solution with ConsumerN where I can pass multiple providers, but I don't see anything similar in Riverpod.

What I have now and it works fine:

final filteredList1 = StreamProvider<FilteredList>((ref) async* {
  final value1 = ref
      .watch(valueProvider1)
      .value;
  final value2 = ref
      .watch(valueProvider2)
      .value;
  yield ref
      .read(repository)
      .filterList(value1, value2);
});

final filteredList1 = StreamProvider<FilteredList>((ref) async* {
  final value3 = ref
      .watch(valueProvider3)
      .value;
  final value4 = ref
      .watch(valueProvider4)
      .value;
  yield ref
      .read(repository)
      .filterList(value3, value4);
});

final filteredList3 = StreamProvider<FilteredList>((ref) async* {
  final value5 = ref
      .watch(valueProvider5)
      .value;
  final value6 = ref
      .watch(valueProvider6)
      .value;
  yield ref
      .read(repository)
      .filterList(value5, value6);
});

final lastFilteredListProvider =
    StreamProvider<FilteredList>((ref) => StreamGroup.merge([
          ref.watch(filteredList1.stream),
          ref.watch(filteredList2.stream),
          ref.watch(filteredList3.stream)
        ]));

And what I would like to achieve, is to not use Stream for that but maybe something like this:

final filteredList1 = Provider<FilteredList>((ref) {
  final value1 = ref
      .watch(valueProvider1)
      .value;
  final value2 = ref
      .watch(valueProvider2)
      .value;
  return ref
      .read(repository)
      .filterList(value1, value2);
});

final filteredList1 = Provider<FilteredList>((ref) {
  final value3 = ref
      .watch(valueProvider3)
      .value;
  final value4 = ref
      .watch(valueProvider4)
      .value;
  return ref
      .read(repository)
      .filterList(value3, value4);
});

final filteredList3 = Provider<FilteredList>((ref) {
  final value5 = ref
      .watch(valueProvider5)
      .value;
  final value6 = ref
      .watch(valueProvider6)
      .value;
  return ref
      .read(repository)
      .filterList(value5, value6);
});

final lastFilteredListProvider =
    Provider<FilteredList>((ref) {
      final filteredList1 = ref.watch(filteredList1);
      final filteredList2 = ref.watch(filteredList2);
      final filteredList3 = ref.watch(filteredList3);
     // EMIT HERE LATEST LIST
});

I think you are most of the way there already.

You can combine providers like you have already and in the case of lists you can emit a new instance of a list when one or more providers being watched update their values.

I noticed you are calling both watch and read in some of your code. It isn't advised to call read when combining providers [ref] . The difference between the 2 methods is you will not be notified of changes when reading and will only get a single value.

I was unsure what FilteredCompanies is but if its just a an alias for a type of List<T> then the following would work.

final lastFilteredListProvider =
    Provider<FilteredCompanies>((ref) {
      final filteredList1 = ref.watch(filteredList1);
      final filteredList2 = ref.watch(filteredList2);
      final filteredList3 = ref.watch(filteredList3);
      return [...filteredList1, ...filteredList2, ...filteredList3];
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM