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

riverpod_graph: don't crash on: 1) provider is a method of instance of another provider 2) recursive watch calls, like: ref.watch(ref.watch(provider)) #2870

Closed
wants to merge 3 commits into from

Conversation

Alexqwesa
Copy link

@Alexqwesa Alexqwesa commented Sep 1, 2023

ConsumerWidgetVisitor: store map of local variables, to solve cases there provider is a method of instance of another provider state, i.e.:

final worker = ref.watch(currentWorker); 
final clients = ref.watch(worker.clientsOf) 
//there: 
class Worker{ 
Provider get clients => clientsOfWorker(this); 
// other code....
}

ConsumerWidgetVisitor: allow recursive watch, like:

ref.watch(provider1(ref.watch(provider2)))  // updated

luketg8 and others added 2 commits September 1, 2023 16:19
…here provider is a method of instance of another provider state, i.e.:

final worker = ref.watch(currentWorker);
final clients = ref.watch(worker.clientsOf)

there:

class Worker{
Provider get clients => clientsOfWorker(this);
// other code....
}
@codecov
Copy link

codecov bot commented Sep 1, 2023

Codecov Report

Merging #2870 (6f1e224) into master (6c9b73c) will not change coverage.
The diff coverage is n/a.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #2870   +/-   ##
=======================================
  Coverage   95.24%   95.24%           
=======================================
  Files          53       53           
  Lines        2252     2252           
=======================================
  Hits         2145     2145           
  Misses        107      107           

@rrousselGit
Copy link
Owner

class Worker{ 
Provider get clients => clientsOfWorker(this); 

We could fail more gracefully, but that's not supposed to be supported. Folks shouldn't do this.
Same goes for ref.watch(ref.watch(provider)).

Providers should exclusively be top-level final variables.

@rrousselGit
Copy link
Owner

First and foremost, this would need testing :)

But given my previous comment, I'm not sure I reasonably want to support this. At best we should have a nice error message I'd say.

In any case, your work is bound to be removed soon enough.
riverpod_graph should move its logic to riverpod_analyzer_utils.

If we want to do such a thing, I'd suggest implementing this in riverpod_analyzer_utils first. Then refactoring riverpod_graph to use it.
But still, we should discuss about whether we truly want to support that; which I'm not sure.

@rrousselGit rrousselGit marked this pull request as draft September 1, 2023 10:20
@Alexqwesa
Copy link
Author

Alexqwesa commented Sep 1, 2023

first, sorry for typo:
ref.watch(ref.watch(provider)) - i mean: ref.watch(provider2(ref.watch(provider1))

Not sure why it's not supported. There are cases where I need to access a specific family member of provider2, and I need to call provider1 first (which I don't actually need)

Providers should exclusively be top-level final variables.

actually, is there a discussion on this topic? (I understand that it may be more challenging to implement, fine if it is the case, but it seems usable.)

and for use cases:

final worker = ref.watch(currentWorker); 
final client = ref.watch(worker.clientsOf).first;
final services = ref.watch(client.servicesOf);
  1. When you type a class instance, you can automatically see all its members in the auto-completion menu of the IDE, which is super nice!
  2. and is simply more readable compared to:
final worker = ref.watch(currentWorker); 
final client = ref.watch(clients(worker)).first;
final services = ref.watch(services(client));

An alternative proposition is as follows(but no auto-completion here(( ):

final worker = ref.watch(currentWorker); 
final client = ref.watch(clients.of(worker)).first;
final service = ref.watch(services.of(client)).first;
final proofs = ref.watch(proofs.of(service));

@Alexqwesa
Copy link
Author

Alexqwesa commented Sep 1, 2023

Anyway, thank for good work and good package))

@Alexqwesa
Copy link
Author

Alexqwesa commented Sep 1, 2023

First and foremost, this would need testing :)

Sorry, did you mean: i should also provide tests? I just used riverpod_graph on my project, and these are the patches that made it work.

Sorry for third patch - i promise, next time i will look into riverpod_analyzer_utils.))

(btw, riverpod_graph didn't crash on my project only if I use all 3 patches)

@rrousselGit
Copy link
Owner

i mean: ref.watch(provider2(ref.watch(provider1))

That's much better. I agree with this one

@rrousselGit
Copy link
Owner

actually, is there a discussion on this topic? (I understand that it may be more challenging to implement, fine if it is the case, but it seems usable.)

Outside of possible memory leak, it's straight up not possible when considering codegen – which is the new recommended syntax

@rrousselGit
Copy link
Owner

Sorry, did you mean: i should also provide tests? I just used riverpod_graph on my project, and these are the patches that made it work.

Yes we need automated tests, to avoid regressions

@Alexqwesa
Copy link
Author

Alexqwesa commented Sep 1, 2023

Yes we need automated tests, to avoid regressions

ok, next patch will be with tests

btw, the third patch was a fix for this use case:

final serviceProofAtDate =
    Provider.family<(List<Proof>, ProofList), ClientService>(
  (ref, service) {
    final proofList = proofListProvider(
      contractId: service.contractId,
      // another 6 parameters here...
    );

    return ref.watch(proofList);  // local variable proofList
  },
);

@rrousselGit
Copy link
Owner

Folks shouldn't do this either.

Sure, the graph shouldn't crash. But it would at least warn

All usages of ref.read/watch/listen must be statically analysable. This is important for certain features which rely on static analysis

@rrousselGit
Copy link
Owner

I'll close this as riverpod_graph needs an effective rewrite and initial release.

This problem should fix itself by switching to riverpod_analyzer_utils.

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

Successfully merging this pull request may close these issues.

3 participants