Skip to content

selectAsync does not update immediately after invalidate #3959

Open
@ksatoudeveloper

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions