Open AhmedLSayed9 opened 2 weeks ago
Currently you can do:
final sub = ref.listen(provider.notifier, (_) {});
sub.read().someMethod();
try {
await Navigator.push();
} finally {
sub.close();
}
Currently you can do:
final sub = ref.listen(provider.notifier, (_) {}); sub.read().someMethod(); try { await Navigator.push(); } finally { sub.close(); }
This is good enough, but unfortunately this won't work with the common go_router's method .go
as it's synchronous.
Maybe for .go
we can just do:
try {
SomeRoute().go(context);
await Future.delayed(someDuration);
} finally {
sub.close();
}
Until #108764 is resolved
Consider changing the implementation to pass the init parameter(s) in the route and initializing the edit provider in the target page. Initializing the edit provider before navigating is effectively using it as a global variable (imperative).
In our app, when a user selects an item to edit in another page/dialog, our route includes the ID of the selected item. The edit page uses the given route parameter to watch
the edit provider that is a .autoDispose.family
where the family value is the passed ID. We do have another provider that caches our objects that the edit provider reads the object data from. If your only data source is the list in the original page you can use the GoRouterState.extra
parameter to pass an arbitrary data object.
Passing init parameters in the route makes the implementation more "declarative". This removes the timing issue where during async navigation processing RiverPod can dispose of unused states. Also on the web where the user can easily do back navigation the previous item edits are (can be) restored (updated objects need additional handling/caching).
Consider changing the implementation to pass the init parameter(s) in the route and initializing the edit provider in the target page. Initializing the edit provider before navigating is effectively using it as a global variable (imperative).
In our app, when a user selects an item to edit in another page/dialog, our route includes the ID of the selected item. The edit page uses the given route parameter to
watch
the edit provider that is a.autoDispose.family
where the family value is the passed ID. We do have another provider that caches our objects that the edit provider reads the object data from. If your only data source is the list in the original page you can use theGoRouterState.extra
parameter to pass an arbitrary data object.Passing init parameters in the route makes the implementation more "declarative". This removes the timing issue where during async navigation processing RiverPod can dispose of unused states. Also on the web where the user can easily do back navigation the previous item edits are (can be) restored (updated objects need additional handling/caching).
The use-case for this approach is to initialize and pass some data that's already there or can't be fetched through an init parameter (which we'd pass it as path/query parameter ofc).
Using GoRouterState.extra
parameter should work but there're 2 obstacles here:
Overall I think this is more of a GoRouter issue than a Riverpod issue.
Navigator has various ways to handle this, such as Navigator.push(route) ; which allows pushing a route with custom values.
We need to find some reliable approach for initializing some values before pushing a route and add it to documentation.
There was a related issue #1329 that was asking for a way to
auto dispose after first listener
, which is one of the approaches to solve this matter. but as Remi mentioned, it seems dangerous, as if the "first listener" is never added for some reason, the disposal will never happen.Another proposed approach is to do something like:
but this won't work with the common go_router's method
.go
as it's synchronous. Note: There's an issue asking for it to be asynchronous, but it's there for a very long time.