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
[go_router] Redirection with Riverpod example #112915
Comments
@creativecreatorormaybenot (Since Riverpod is supposed to be a better version of Provider, I think adding Riverpod examples for both "Redirection" and "Asynchronous Redirection" make sense to me) |
On Riverpod's documentation pages, under the 3rd party examples folder on the left, you'll find "GoRouter with Riverpod", which is a repo I've made a while ago you can explore to check out possible solutions to integrate GoRouter and Riverpod together. I also want to add that while "This setup is so much cleaner and easier to grasp than the existing Redirection example using provider", there are some (simple) caveats to be aware of. In your example snippet above, The above (and more caveats) are what motivated this repo to not only write down a simple example, but to properly analyze different possible approaches. Indeed, very soon I am going to add (there) the following new features:
Feedback is highly appreciated. |
@TahaTesser That would be super awesome! I certainly think that having Riverpod examples makes sense 👍 I would be glad to review 👌 |
Hi @lucavenir, this is not right. If you look at the snippet, you will see that I consciously pass a
I very highly appreciate this effort 🙏 Thanks @lucavenir. However, I am sorry to tell you that I do not like the solutions in this repo. Especially piping all provider changes into listenables seems awful to maintain. Feel free to try out my proposed solution and report if you can find any problems with it. This is also why I would really love to have an About rebuildsNote that you are of course right that the class App extends ConsumerWidget {
const App({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final router = ref.watch(routerProvider);
return MaterialApp.router(
routerConfig: router,
);
}
} Will always rebuild when one of the dependencies of the |
One crazy idea I have is removing If we further optimize |
I've been sloppy in reading your code - sorry! Thanks for the detailed explanation. I'll test this out better later, as I can't seem to avoid rebuilds with just that
I'm obsessed with best practices and I can't agree more! The repo looks like this (atm) because:
If those examples (once corrected) contribute into a "Flutter-recommended" approach, it would be awesome and it would answer a lot of questions arising from the Riverpod's community.
I absolutely agree with this. See the above sentences. |
@creativecreatorormaybenot Do you mind take a look at this branch? I'm trying your suggestion but I still seeing the "root widget" rebuilding, there. |
I am not sure what the "root widget" in your setup means @lucavenir, but here you go: https://dartpad.dev/0a77fd6105aeee44858b794e17e83ffc Here is an in-depth showcase 💯 Here we have (sound on 🔈).. Screen.Recording.2022-10-05.at.22.19.27.mp4Note that the |
Thank you @creativecreatorormaybenot for the in-depth explanation!! This is way clearer. I guess I'm still confused by Flutter's |
Hi @creativecreatorormaybenot ! I've updated the examples in this repo, thanks to you! I've cited you as a contributor, but I'm unsure on how to give you more credit than that 😛 Your feedback would be highly appreciated - and I'm guessing that the |
I really appreciate the sample @lucavenir. The crediting is fine. I think a link to the issue would help for context 🙂 Note that I discovered a problem. In the case that you do not cover all of your routes in your The workaround for this is adding: ...
// We need to have access to the previous location of the router. Otherwise, we would start from '/' on rebuild.
GoRouter? _previousRouter;
final routerProvider = Provider((ref) {
return GoRouter(
initialLocation: _previousRouter?.location,
...,
);
}); I am not the biggest fan of this since it is even less clean (with the router being outside of any providers). However, it does work and is solid / non-fragile in theory. Another implication is that modals will never work with this approach, i.e. routes that are pushed via That is to say, I still greatly prefer this method over the previous methods. Although, we should be aware of the limitations. I really like your samples - good job! They are not complex enough to have encountered the edge cases I mentioned, so it might be worth playing with it a bit more to discover these as well 👍 |
This solution is not working as shown in the video on the latest stable channel |
It may be that you skipped one of the steps I described @Neelansh-ns. I just tested the Gist at https://dartpad.dev/0a77fd6105aeee44858b794e17e83ffc and it works for me. |
Hi there, I want to share some thoughts.
|
@creativecreatorormaybenot Would like to ask on this. I actually liked your provided solution as everything make sense in first look. However,
What was your solution on handling modals on top of the route stack? And as for this. How do you update the ...
// We need to have access to the previous location of the router. Otherwise, we would start from '/' on rebuild.
GoRouter? _previousRouter;
final routerProvider = Provider((ref) {
return GoRouter(
initialLocation: _previousRouter?.location,
...,
);
}); |
creativecreatorormaybenot |
A note on |
Hi there, I solved this problem by creating a router provider that who takes care about update the router every time the auth state changes. I did some tests but i'm not sure if is conceptually right or not, so I would appreciate it if you could give me some feedback. RouterNotifier:
In the MaterialApp i have just added the watcher to the gorouter notifier value
Than this is the function that create the GoRouter object
Thank you for your feedback! |
This is a request to add an example to the
go_router
package that shows how to set up redirection with Riverpod.Use case
go_router
is currently not very well documented and so it took me (as an individual who is familiar with how the different parts of the framework work) quite a while to figure out a solid way to usego_router
withflutter_riverpod
properly to handle a sign-in flow.Proposal
Because of that, I feel like the existing example catalog should be updated with another sample to complement "Redirection" and "Asynchronous Redirection".
This is mostly because it works fairly differently under the hood.
Is this something you would be willing to integrate into the package? I would also be willing to contribute the example.
I think this would be very beneficial to also ensure that updates to the package do not break this setup.
Edit: sample here dartpad.dev & explanation here issuecomment-1269053217.
Setup
This method makes use of the fact that reconstructing
GoRouter
will callredirect
again.That means that by providing a
redirect
function that depends on providers, we can both handle calls toredirect
caused by internal calls (Navigator.pop
,context.go
, etc.) as well as the providers updating.It looks something like this:
This setup is so much cleaner and easier to grasp than the existing Redirection example using
provider
.Also note that I was not able to set this up using
refreshListenable
, which is not documented, confusing, and also does not work correctly from what I can tell (it can cause invalid states). Furthermore, therefreshListenable
setup seems way more hacky than theriverpod
setup above to begin with.In conclusion, I think that this method is pretty powerful and I would like to see it included in the package publicly somehow in order to ensure that others can use it and it can be maintained (although it should always work if the package is implemented correctly and checks for equality properly without throwing away the widget tree).
The text was updated successfully, but these errors were encountered: