'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
});
Solution 1:[1]
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];
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Graham Smith |
