requireValue property

ValueT get requireValue

If hasValue is true, returns the value. Otherwise if hasError, rethrows the error. Finally if in loading state, throws a AsyncValueIsLoadingException.

This has two main uses:

  • Inside widgets, it is used for when the UI assumes that value is always present (thanks to loading/error states being handled at a different level).
  • Inside providers, this enables chaining asynchronous providers in a synchronous manner..

Chaining asynchronous providers synchronously.

When AsyncValueIsLoadingException (thrown by requireValue during loading states) is thrown within a provider's initialization, Riverpod will silence it. Combined with the fact that Ref.watch rebuilds a provider when the dependency changes, this enables combining asynchronous providers in a synchronous manner.

The following example adds two numbers obtained asynchronously, in a synchronous manner. This ensures that within the same frame where one of those asynchronous providers updates, the sum is immediately updated.

// We use FutureProvider + AsyncValue to sycnhronously combine asynchronous providers.
// Notice how the callback of FutureProvider is not marked as async.
final sumProvider = FutureProvider<User>((ref) {
  AsyncValue<int> value = ref.watch(someProvider);
  AsyncValue<int> anotherValue = ref.watch(anotherProvider);

  return value.requireValue + anotherValue.requireValue;
});

Note that this usage is only valid within providers that are expected to create a FutureOr (cf FutureProvider/AsyncNotifierProvider).

Implementation

ValueT get requireValue {
  if (hasValue) return value as ValueT;
  if (hasError) {
    assert(this is! AsyncData, 'Bad state');
    throwProviderException(error!, stackTrace!);
  }

  assert(this is! AsyncData, 'Bad state');
  throw AsyncValueIsLoadingException._(this);
}