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

ref.listen not invoked when state changed with the same value #3411

Closed
minhnt3 opened this issue Mar 10, 2024 · 1 comment
Closed

ref.listen not invoked when state changed with the same value #3411

minhnt3 opened this issue Mar 10, 2024 · 1 comment
Assignees
Labels
enhancement New feature or request needs triage

Comments

@minhnt3
Copy link

minhnt3 commented Mar 10, 2024

Problem

I know that ref.listen will not invoked when state changed with the same value from Riverpod 2.x. This is a feature in most cases but it may lead to a bug in some cases. Let's assume we are implementing the pagination feature. We have to listen to state changes to add data to PagingController.

final provider = StateProvider<List<int>>((ref) => []);

ref.listen(
        provider,
        (previous, next) {
         if (next.isEmpty) pagingController.appendLastPage(next);
         else pagingController.appendPage(next);
        },
);

Of course, the default state is an empty list. When we fetch data of the first page, if it also returns an empty list, the ref.listen will not triggered and thus the pagingController.appendLastPage will never be called.

In another case, when data of the first page is [1,2,3] and data of the second page is [1,2,3] as well, the ref.listen will not triggered and we will lose data of the second page. It's a bug. Of course, we can fix them by using some flags but it make code so messy.

Solution

I think we should add a boolean parameter to ref.listen that allow us using it flexiblely or we create a new listen method to use in some special cases like these. Thanks.

@rrousselGit
Copy link
Owner

This is unrelated to ref.listen. ref.listen doesn't filter anything.
Your issue is how you modify your state. It's the provider that filters notification.

For that purpose, there's already ref.notifyListeners() which providers can call if they mutated their state instead of cloning it. Sounds like you want a way to call notifyListeners when using StateProvider.

I'd suggest using Provider instead of StateProvider, and making a generic object that exposes notifyListeners.

class Box<T> {
  Box(this._ref, this.value);
  final Ref<T> _ref;

  T value;

  void notifyListeners() => _ref.notifyListeners();
}

Then used as:

final provider = Provider<Box<List<int>>>((ref) => Box(ref, []));


ref.read(provider)
  ..value.add(42)
  ..notifyListeners();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request needs triage
Projects
None yet
Development

No branches or pull requests

2 participants