rrousselGit / riverpod

A reactive caching and data-binding framework. Riverpod makes working with asynchronous code a breeze.
https://riverpod.dev
MIT License
6.15k stars 942 forks source link

invalidation forwarding #3675

Open TekExplorer opened 1 month ago

TekExplorer commented 1 month ago

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 commented 1 month ago

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

TekExplorer commented 1 month ago

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 commented 1 month ago

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

For instance:

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 commented 1 month ago

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 commented 1 month ago

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