Skip to content

Commit

Permalink
Update docs a bit (#2300)
Browse files Browse the repository at this point in the history
  • Loading branch information
rrousselGit authored Mar 10, 2023
1 parent 77481e0 commit 6031730
Show file tree
Hide file tree
Showing 22 changed files with 203 additions and 117 deletions.
8 changes: 8 additions & 0 deletions packages/riverpod/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## Unreleased patch


- Deprecated the generic parameter of `Family`.
This will enable implementing generic providers in `riverpod_generator` once
it is removed.
- Updated documentation

## 2.3.1 - 2023-03-09

- Updated `AsyncValue.value/valueOrNull` docs to cover the "previous value" cases (thanks to @AhmedLSayed9)
Expand Down
53 changes: 26 additions & 27 deletions packages/riverpod/lib/src/async_notifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import 'listenable.dart';
import 'notifier.dart';
import 'pragma.dart';
import 'result.dart';
import 'stream_provider.dart';

part 'async_notifier/auto_dispose.dart';
part 'async_notifier/auto_dispose_family.dart';
part 'async_notifier/base.dart';
part 'async_notifier/family.dart';

part 'stream_notifier.dart';
part 'stream_notifier/auto_dispose.dart';
part 'stream_notifier/auto_dispose_family.dart';
Expand All @@ -32,13 +32,16 @@ abstract class AsyncNotifierBase<State> {

void _setElement(ProviderElementBase<AsyncValue<State>> element);

/// The value currently exposed by this [Notifier].
/// The value currently exposed by this [AsyncNotifier].
///
/// Defaults to [AsyncLoading] inside the [AsyncNotifier.build] method.
///
/// Invoking the setter will notify listeners if [updateShouldNotify] returns true.
/// By default, this will compare the previous and new value using [identical].
/// By default, this always notifies listeners (unless going from "loading"
/// to "loading", in which case the change is ignored).
///
/// Reading [state] if the provider is out of date (such as if one of its
/// dependency has changed) will trigger [Notifier.build] to be re-executed.
/// dependency has changed) will trigger [AsyncNotifier.build] to be re-executed.
@protected
AsyncValue<State> get state {
_element.flush();
Expand All @@ -62,8 +65,8 @@ abstract class AsyncNotifierBase<State> {
/// If [state] is modified before [AsyncNotifier.build] completes, then [future]
/// will resolve with that new [state] value.
///
/// The future will fail if [AsyncNotifier.build] throws or returns a future
/// that fails.
/// The future will fail if [state] is in error state. In which case the
/// error will be the same as [AsyncValue.error] and its stacktrace.
/// {@endtemplate}
Future<State> get future {
_element.flush();
Expand All @@ -73,12 +76,17 @@ abstract class AsyncNotifierBase<State> {
/// A function to update [state] from its previous value, while
/// abstracting loading/error cases for [state].
///
/// This method neither causes [state] to go back to "loading" while the
/// operation is pending. Neither does it cause [state] to go to error state
/// if the operation fails.
///
/// If [state] was in error state, the callback will not be invoked and instead
/// the error will be returned. Alternatively, [onError] can specified to
/// gracefully handle error states.
///
/// See also:
/// - [future], for manually awaiting the resolution of [state].
/// - [AsyncValue.guard], and alternate way to perform asynchronous operations.
@protected
Future<State> update(
FutureOr<State> Function(State) cb, {
Expand All @@ -92,31 +100,22 @@ abstract class AsyncNotifierBase<State> {
}

/// A method invoked when the state exposed by this [AsyncNotifier] changes.
/// It compares the previous and new value, and return whether listeners
/// should be notified.
///
/// By default, the previous and new value are compared using [identical]
/// for performance reasons.
///
/// Doing so ensured that doing:
///
/// ```dart
/// state = const AsyncData(42);
/// state = const AsyncData(42);
/// ```
///
/// does not notify listeners twice.
///
/// But at the same time, for very complex objects with potentially dozens
/// if not hundreds of properties, Riverpod won't deeply compare every single
/// As opposed to with [Notifier.updateShouldNotify], this method
/// does not filter out changes to [state] that are equal to the previous
/// value.
/// By default, any change to [state] will emit an update.
/// This method can be overridden to implement custom filtering logic if that
/// is undesired.
///
/// This ensures that the comparison stays efficient for the most common scenarios.
/// But it also means that listeners should be notified even if the
/// previous and new values are considered "equal".
/// The reasoning for this default behavior is that [AsyncNotifier.build]
/// returns a [Future]. As such, the value of [state] typically transitions
/// from "loading" to "data" or "error". In that scenario, the value equality
/// does not matter. Checking `==` would only hinder performances for no reason.
///
/// If you do not want that, you can override this method to perform a deep
/// comparison of the previous and new values.
/// See also:
/// - [ProviderBase.select] and [AsyncSelector.selectAsync], which are
/// alternative ways to filter out changes to [state].
@protected
bool updateShouldNotify(AsyncValue<State> previous, AsyncValue<State> next) {
return FutureHandlerProviderElementMixin.handleUpdateShouldNotify(
Expand Down
8 changes: 6 additions & 2 deletions packages/riverpod/lib/src/async_notifier/auto_dispose.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ abstract class BuildlessAutoDisposeAsyncNotifier<State>
AutoDisposeAsyncNotifierProviderRef<State> get ref => _element;
}

/// {@macro riverpod.asyncnotifier}
/// {@macro riverpod.async_notifier_provider}
///
/// {@macro riverpod.async_notifier_provider_modifier}
abstract class AutoDisposeAsyncNotifier<State>
extends BuildlessAutoDisposeAsyncNotifier<State> {
/// {@macro riverpod.asyncnotifier.build}
Expand All @@ -32,7 +34,9 @@ abstract class AutoDisposeAsyncNotifier<State>
abstract class AutoDisposeAsyncNotifierProviderRef<T>
implements AsyncNotifierProviderRef<T>, AutoDisposeRef<AsyncValue<T>> {}

/// {@macro riverpod.asyncnotifier}
/// {@macro riverpod.async_notifier_provider}
///
/// {@macro riverpod.async_notifier_provider_modifier}
typedef AutoDisposeAsyncNotifierProvider<
NotifierT extends AutoDisposeAsyncNotifier<T>, T>
= AutoDisposeAsyncNotifierProviderImpl<NotifierT, T>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
part of '../async_notifier.dart';

/// {@macro riverpod.asyncnotifier}
/// {@macro riverpod.async_notifier_provider}
///
/// {@macro riverpod.async_notifier_provider_modifier}
abstract class AutoDisposeFamilyAsyncNotifier<State, Arg>
extends BuildlessAutoDisposeAsyncNotifier<State> {
/// {@template riverpod.notifier.family_arg}
Expand All @@ -17,7 +19,9 @@ abstract class AutoDisposeFamilyAsyncNotifier<State, Arg>
FutureOr<State> build(Arg arg);
}

/// {@macro riverpod.asyncnotifier}
/// {@macro riverpod.async_notifier_provider}
///
/// {@macro riverpod.async_notifier_provider_modifier}
typedef AutoDisposeFamilyAsyncNotifierProvider<
NotifierT extends AutoDisposeFamilyAsyncNotifier<T, Arg>, T, Arg>
= AutoDisposeFamilyAsyncNotifierProviderImpl<NotifierT, T, Arg>;
Expand Down
25 changes: 25 additions & 0 deletions packages/riverpod/lib/src/async_notifier/base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ abstract class BuildlessAsyncNotifier<State> extends AsyncNotifierBase<State> {
/// {@template riverpod.asyncnotifier}
/// A [Notifier] implementation that is asynchronously initialized.
///
/// This is similar to a [FutureProvider] but allows to perform side-effects
/// by defining public methods.
///
/// It is commonly used for:
/// - Caching a network request while also allowing to perform side-effects.
/// For example, `build` could fetch information about the current "user".
Expand All @@ -30,6 +33,8 @@ abstract class BuildlessAsyncNotifier<State> extends AsyncNotifierBase<State> {
/// - Initializing a [Notifier] from an asynchronous source of data.
/// For example, obtaining the initial state of [Notifier] from a local database.
/// {@endtemplate}
///
/// {@macro riverpod.async_notifier_provider_modifier}
// TODO add usage example
abstract class AsyncNotifier<State> extends BuildlessAsyncNotifier<State> {
/// {@template riverpod.asyncnotifier.build}
Expand All @@ -53,6 +58,23 @@ abstract class AsyncNotifier<State> extends BuildlessAsyncNotifier<State> {
abstract class AsyncNotifierProviderRef<T> implements Ref<AsyncValue<T>> {}

/// {@template riverpod.async_notifier_provider}
/// A provider which creates and listen to an [AsyncNotifier].
///
/// This is similar to [FutureProvider] but allows to perform side-effects.
///
/// The syntax for using this provider is slightly different from the others
/// in that the provider's function doesn't receive a "ref" (and in case
/// of `family`, doesn't receive an argument either).
/// Instead the ref (and argument) are directly accessible in the associated
/// [AsyncNotifier].
/// {@endtemplate}
///
/// {@template riverpod.async_notifier_provider_modifier}
/// When using `autoDispose` or `family`, your notifier type changes.
/// Instead of extending [AsyncNotifier], you should extend either:
/// - [AutoDisposeAsyncNotifier] for `autoDispose`
/// - [FamilyAsyncNotifier] for `family`
/// - [AutoDisposeFamilyAsyncNotifier] for `autoDispose.family`
/// {@endtemplate}
typedef AsyncNotifierProvider<NotifierT extends AsyncNotifier<T>, T>
= AsyncNotifierProviderImpl<NotifierT, T>;
Expand All @@ -68,6 +90,8 @@ class AsyncNotifierProviderImpl<NotifierT extends AsyncNotifierBase<T>, T>
extends AsyncNotifierProviderBase<NotifierT, T>
with AlwaysAliveProviderBase<AsyncValue<T>>, AlwaysAliveAsyncSelector<T> {
/// {@macro riverpod.async_notifier_provider}
///
/// {@macro riverpod.async_notifier_provider_modifier}
AsyncNotifierProviderImpl(
super._createNotifier, {
super.name,
Expand Down Expand Up @@ -138,6 +162,7 @@ typedef CancelAsyncSubscription = void Function();

/// Mixin to help implement logic for listening to [Future]s/[Stream]s and setup
/// `provider.future` + convert the object into an [AsyncValue].
@internal
mixin FutureHandlerProviderElementMixin<T>
on ProviderElementBase<AsyncValue<T>> {
/// A default implementation for [ProviderElementBase.updateShouldNotify].
Expand Down
8 changes: 5 additions & 3 deletions packages/riverpod/lib/src/async_notifier/family.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
part of '../async_notifier.dart';

/// {@macro riverpod.asyncnotifier}
///
/// {@macro riverpod.async_notifier_provider_modifier}
abstract class FamilyAsyncNotifier<State, Arg>
extends BuildlessAsyncNotifier<State> {
/// {@template riverpod.notifier.family_arg}
Expand All @@ -27,9 +29,9 @@ abstract class FamilyAsyncNotifier<State, Arg>
FutureOr<State> build(Arg arg);
}

/// {@template riverpod.async_notifier_family_provider}
/// The provider for [AsyncNotifierProviderFamily].
/// {@endtemplate}
/// {@macro riverpod.async_notifier_provider}
///
/// {@macro riverpod.async_notifier_provider_modifier}
typedef AsyncNotifierFamilyProvider<
NotifierT extends FamilyAsyncNotifier<T, Arg>, T, Arg>
= FamilyAsyncNotifierProviderImpl<NotifierT, T, Arg>;
Expand Down
Loading

0 comments on commit 6031730

Please sign in to comment.