Skip to content

Commit

Permalink
fixes #1997
Browse files Browse the repository at this point in the history
  • Loading branch information
rrousselGit committed Dec 21, 2022
1 parent 56466bb commit 0e54b7a
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 9 deletions.
1 change: 1 addition & 0 deletions packages/riverpod/CHANGELOG.md
Expand Up @@ -2,6 +2,7 @@

- Update dependencies.
- fixes an exception on newer Dart versions
- fixes an edge-case where `FutureProvider`/`AsyncNotifier` did not emit the new state when the created `Future` completed (#1997)

## 2.1.1

Expand Down
6 changes: 0 additions & 6 deletions packages/riverpod/lib/src/async_notifier/base.dart
Expand Up @@ -173,8 +173,6 @@ mixin FutureHandlerProviderElementMixin<T>
}

void _dataTransition(T value) {
_builtFuture = null;

final completer = _futureCompleter;
if (completer != null) {
completer.complete(value);
Expand All @@ -192,8 +190,6 @@ mixin FutureHandlerProviderElementMixin<T>
}

void _errorTransition(Object err, StackTrace stackTrace) {
_builtFuture = null;

final completer = _futureCompleter;
if (completer != null) {
completer
Expand Down Expand Up @@ -253,7 +249,6 @@ mixin FutureHandlerProviderElementMixin<T>
if (_builtFuture == futureOr) {
_errorTransition(error, stackTrace);
setState(AsyncError<T>(error, stackTrace));
_builtFuture = null;
}
},
);
Expand Down Expand Up @@ -295,7 +290,6 @@ mixin FutureHandlerProviderElementMixin<T>
);
}
}

super.dispose();
}

Expand Down
Expand Up @@ -509,7 +509,7 @@ void main() {
});

test(
'after manually going back to loading, dispose throws StateError',
'after manually going back to loading, resolves with last future result',
() async {
final container = createContainer();
final completer = Completer<int>.sync();
Expand All @@ -527,6 +527,30 @@ void main() {

completer.complete(42);

await expectLater(future, completion(42));
},
);

test(
'if going back to loading after future resolved, throws StateError',
() async {
final container = createContainer();
final completer = Completer<int>.sync();
final provider = factory.simpleTestProvider<int>(
(ref) => completer.future,
);

container.read(provider);

completer.complete(42);

container.read(provider.notifier).state = const AsyncData(42);
container.read(provider.notifier).state = const AsyncLoading<int>();

final future = container.read(provider.future);

container.dispose();

await expectLater(future, throwsStateError);
},
);
Expand All @@ -550,8 +574,13 @@ void main() {

completer.complete(42);

expect(sub.read().future, completion(21));
verifyZeroInteractions(listener);
expect(sub.read().future, completion(42));
final capture =
verifyOnly(listener, listener(captureAny, captureAny)).captured;

expect(capture.length, 2);
expect(capture.first, completion(21));
expect(capture.last, completion(42));
});

test('resolves with the new state when notifier.state is changed',
Expand Down
Expand Up @@ -74,6 +74,33 @@ void main() {
expect(container.read(autoDispose).value, 84);
});

test('Does not skip return value if ref.state was set', () async {
final completer = Completer<void>();
final provider = FutureProvider<int>((ref) async {
await Future<void>.value();
ref.state = const AsyncData(1);
await Future<void>.value();
ref.state = const AsyncData(2);
await Future<void>.value();
completer.complete();
return 3;
});
final container = createContainer();
final listener = Listener<AsyncValue<int>>();

container.listen(provider, listener, fireImmediately: true);

await completer.future;
await container.pump();

verifyInOrder([
listener(null, const AsyncLoading<int>()),
listener(const AsyncLoading<int>(), const AsyncData(1)),
listener(const AsyncData(1), const AsyncData(2)),
listener(const AsyncData(2), const AsyncData(3)),
]);
});

test('supports family overrideWith', () {
final family = FutureProvider.family<String, int>((ref, arg) => '0 $arg');
final autoDisposeFamily = FutureProvider.autoDispose.family<String, int>(
Expand Down

0 comments on commit 0e54b7a

Please sign in to comment.