Open
Description
Describe the bug
I encountered an issue when using selectAsync with invalidate().
The provider using watch updates as expected, but the provider using selectAsync does not update immediately after invalidate().
- When using refresh() instead of invalidate(), the provider updates as expected.
- When add Future.delayed after invalidate(), the provider updates as expected.
- When not using selectAsync, the provider updates as expected.
To Reproduce
import 'dart:math';
import 'package:riverpod/riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:test/test.dart';
part 'riv_test.g.dart';
@Riverpod(keepAlive: true)
Random random(Ref ref) {
return Random(1);
}
@Riverpod(keepAlive: true)
Future<({int h, int r})> cone(Ref ref) async {
final random = ref.watch(randomProvider);
final cone = (
h: random.nextInt(10),
r: random.nextInt(10)
); // (h: 4, r: 7), (h: 5, r: 9), ...
return cone;
}
@Riverpod(keepAlive: true)
Future<double> baseAreaSelectAsync(Ref ref) async {
final r = await ref.watch(coneProvider.selectAsync((c) => c.r));
return r * r * pi;
}
@Riverpod(keepAlive: true)
Future<double> baseArea(Ref ref) async {
final (h: _, r: r) = await ref.watch(coneProvider.future);
return r * r * pi;
}
void main() {
late ProviderContainer container;
setUp(() {
container = ProviderContainer();
});
test('watch-selectAsync invalidate', () async {
await expectLater(
container.read(baseAreaSelectAsyncProvider.future),
completion(153.93804002589985),
);
container.invalidate(coneProvider);
await expectLater(
container.read(baseAreaSelectAsyncProvider.future),
completion(254.46900494077323), // Failed actual 153.93804002589985
);
});
test('watch-selectAsync refresh', () async {
await expectLater(
container.read(baseAreaSelectAsyncProvider.future),
completion(153.93804002589985),
);
await container.refresh(coneProvider.future);
await expectLater(
container.read(baseAreaSelectAsyncProvider.future),
completion(254.46900494077323),
);
});
test('watch-selectAsync invalidate delay', () async {
await expectLater(
container.read(baseAreaSelectAsyncProvider.future),
completion(153.93804002589985),
);
container.invalidate(coneProvider);
await Future.delayed(Duration.zero);
await expectLater(
container.read(baseAreaSelectAsyncProvider.future),
completion(254.46900494077323),
);
});
test('watch invalidate', () async {
await expectLater(
container.read(baseAreaProvider.future),
completion(153.93804002589985),
);
container.invalidate(coneProvider);
await expectLater(
container.read(baseAreaProvider.future),
completion(254.46900494077323),
);
});
test('watch refresh', () async {
await expectLater(
container.read(baseAreaProvider.future),
completion(153.93804002589985),
);
await container.refresh(coneProvider.future);
await expectLater(
container.read(baseAreaProvider.future),
completion(254.46900494077323),
);
});
tearDown(() {
container.dispose();
});
}
Expected behavior
When coneProvider is invalidated, calling container.read(baseAreaSelectAsyncProvider.future) should immediately return the updated value.
Activity