Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes #1997 #2019

Merged
merged 1 commit into from Dec 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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