Closed derolf closed 3 years ago
That would be the responsibility of the widget doing the pull-to-refresh
The widget should keep a cache on the latest value and use it during loading
or error
status.
I know, but then the logic in the widget get’s quite complex since using “when” on the value will go to the “loading” branch, but your content widget usually sits in the “data” branch.
Also, you might have quite a few places watching the same FutureProvider.
i thought it would be nicer to generalize it on the riverpod side.
I agree. But I still don't think that that AsyncValue
is the correct place
This is the typical use-case for hooks.
For example you could do:
AsyncValue<T> useLastValidAsyncValue<T>(AsyncValue<T> value) {
return useValueChanged<AsyncValue<T>, AsyncValue<T>>(
value,
(_, previousValidValue) {
return value.data ?? previousValidValue;
},
);
}
It then allows:
Widget build(context) {
final AsyncValue<int> value = useProvider(futureProvider);
// after calling `context.refresh(futureProvider)`,
// lastValueValid will contain the last data instead of loading state
final AsyncValue<int> lastValueValid = useLastValidAsyncValue(value);
// TODO return lastValueValue.when(...)
}
You could easily tweak this hook to show snackbars on error after a pull-to-refresh too.
We are using the following hook very successfully to access the last update to a FutureProvider
while a new update is being processed. This is very handy when dealing e.g. with Firestore live updates.
/// useProviderCached returns the freshest non-loading [AsyncValue] from a
/// [ProviderListenable].
AsyncValue<T> useProviderCached<T>(ProviderListenable<AsyncValue<T>> provider) {
final value = useProvider(provider);
final cache = useState<AsyncValue<T>>(value);
if (!(value is AsyncLoading)) {
cache.value = value;
return value;
}
if (cache.value != null && !(cache.value is AsyncLoading)) {
return cache.value;
}
cache.value = value;
return value;
}
Thanks @fpoppinga
For anyone else who needs this, I have put useLastValidAsyncData.html
into my noob
package:
https://pub.dev/documentation/noob/latest/noob/useLastValidAsyncData.html
Currently, FutureProvider‘s AsyncValue had 3 states. It’s possible to retrigger the Future by using refresh.
However, that way the data is lost since the FP is reset.
For proper pull-to-refresh you need a fourth state “refreshing” that lets you access the “stale” data that was available before calling refresh.