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

invalidation forwarding #3675

Open
TekExplorer opened this issue Jul 24, 2024 · 7 comments
Open

invalidation forwarding #3675

TekExplorer opened this issue Jul 24, 2024 · 7 comments
Assignees
Labels
enhancement New feature or request

Comments

@TekExplorer
Copy link

Often, we will do something like this:

@riverpod
Task task(TaskRef ref) => getTask();

@riverpod
String taskName(TaskNameRef ref) => ref.watch(taskProvider).name;

This is great, but now if i wanted to invalidate or refresh taskNameProvider to get the latest value, it doesn't actually do anything, since we needed to invalidate/refresh taskProvider instead.

This request is to define some kind of invalidation forwarding. perhaps something like

@riverpod
String taskName(TaskNameRef ref) {
  ref.forwardInvalidation(taskProvider);
  return ref.watch(taskProvider).name;

which will decrease the overhead on callers, such that they no longer need to know the implementation

the only thing I can think of otherwise would be to do something like ref.onDispose(() => ref.invalidate(taskProvider)) but that doesn't actually work, since taskNameProvider could dispose for other reasons.

@rrousselGit
Copy link
Owner

The general solution is to use a notifier and expose a method that invalidates everything you want in it.

@TekExplorer
Copy link
Author

I can understand that, but I now need to remember to use a specific notifier method.

I also need a notifier, even if it might not otherwise be necessary.

Being able to forward Invalidations would allow us to naiively use ref.invalidate.

Currently, it would just rerun the provider itself with the existing dependencies, which ends up being completely pointless for computed values.

@rrousselGit
Copy link
Owner

The problem is, there are lots of subtilities with the idea of "when invalidating X, invalidate Y too".

For instance:

  • does ref.refresh count?
  • What about ref.watch. When the dependency changes, do we invalidate the "forward" too?
  • And what about the new automatic retry in 3.0?

All of these rely on the "invalidate" mechanism. And it's highly likely that sometimes the answer to those questions is yes, and sometimes it's no, based on the context.

So for that purpose, I'd much rather stick to recommending a Notifier with a method. It's flexible, and doesn't involve new APIs (which adds complexity and can be error prone).

@TekExplorer
Copy link
Author

TekExplorer commented Jul 25, 2024

As far as I'm concerned, a dependency change is more of a "dirty" as opposed to an "invalidate" and shouldn't forward

A refresh is just an invalidate + read, so I don't see why it wouldn't act the same.

Automatic retry should operate on the forwarded one, because that's where the retry actually does anything.

All I'm saying is that Invalidations ought to hit the source of truth, and doesn't actually do anything if it invalidates a computed value, since it won't actually change no matter how many times you invalidate it.

@TekExplorer
Copy link
Author

TekExplorer commented Jul 25, 2024

Perhaps simply adding an ref.onInvalidate((bool isRefresh) {}) hook could be plenty.

It doesn't actively encourage the pattern, but it does make it possible

@malthee
Copy link

malthee commented Sep 22, 2024

Our team could also require this or something similar, although async, my use case is the following:

  • setupProvider -> Initializes a SDK for the first time and may only run once if successful
  • valueProvider -> calls await ref.watch(setupProvider.future) and gets a value using the SDK dependency.

Now in my code I just want to call ref.refresh(valueProvider) when it has failed. But the problem is when the underlying setupProvider fails, the cached error is thrown again, ergo I would also have to call refresh on the setupProvider also.
This means first checking if the setupProvider has an error state and refreshing it. Although, in most cases I would not want to make the setupProvider public to the UI, as it should only care about the values, not how the setup works in the background.

For this case it would be nice to control the propagation of invalidate and refresh inside of the providers.
If someone has a nice solution to this or any improvements I would be happy to hear it.

@droidpl
Copy link

droidpl commented Oct 20, 2024

I think having an utility like the one mentioned here can allow us for more flexibility when describing how our providers should behave on invalidation. Although having a NotifierProvider can fix this, it forces to break that responsibility on how that provider works in different parts of the app, while it can condense all its behavior in the same provider, which is much cleaner and easier to read/test.

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

No branches or pull requests

4 participants