A Meditation on Flutter Routing š¤
I have been playing with the go_router package for a couple of weeks now and I am still not sure what to think about it. True, itās a great improvement over the original ānavigation 2.0ā proposals and the general consensus in the community is that it comes down to personal preferences between beamer and go_router. Both get excellent reviews and I have no reason to challenge either.
I also acknowledge that the package is under very active development and things are moving fast. Some of my concerns might have been addressed this week and are just not reflected well in the examples yet.
The problem
But still, something is missing and I am coming more and more to the conclusion that it is not the package, but the concept of route-based navigation in general that I am struggling with.
Disclaimer: At the moment most of my apps are mobile only. Flutter Navigation 2.0 was in part introduced to overcome shortcoming in the origianl Navigation concept for the web.
It seems to me that my problems stem from the fact that my apps usually have a few pages that can be accessed via multiple paths. Often this is a details page that is reachable via various lists or filters. As it happens go_routerās very own books example illustrates the problem perfectly:
The go_router books example app
If you want to follow along you can download and run the go_router examples yourself:
> git clone https://github.com/flutter/packages.git flutter_packages
> cd flutter_packages/packages/go_router/examples
> flutter pub get
> flutter run lib/books/main.com
As is customary, the go_router package contains an examples folder with a few single-file demo apps, all of them reduced to the most basic functionality to showcase a particular go_router call.
The additional books app is included as a slightly more complex demonstration of the entire go_router package. It uses an adaptable bottom navigation bar with three tabs, books, authors, and settings. (Adaptable here means that it changes from bottom navigation to side navigation depending on screen size.)
Two of the tabs, books and authors, allow the user to eventually reach a book details page. The problem arises when returning from the book details page. As a user, I would expect to return to the page/tab I just came from. But since the app implements the transition as a context.go(ā/book/${book.id}ā)
jump, that path information is lost and the user always returns to the books tab.
A similar thing happens with the filter tabs on the books page. Again, the book details page can be opened from any of the filtered lists but on return, the user always gets thrown back to the āallā filter.
In my opinion, the reason is that navigation is implemented by replacing the stack with a new route on every transaction. This works fine if each page is only by a single path and each state can be described by exactly one route. In this case, however, the ābook detailsā state is reachable via multiple paths; expressing the state with a single route causes information loss.
In the image, the red arrows symbolize a path taken by the user. The blue arrow represents the actual route on the stack which will be used as the basis for the back button.
Possible Solutions (Work in Progress!!)
I am busy trying out different approaches to modify the books app example to something that better meets user expectations. Iāll report back on my findings but for now here are some of the approaches I am considering:
More push/pop, less go
Use push/pop to navigate to any page that could be reached by multiple paths. This works but wouldnāt it wipe out the advantages of using route-based navigation in the first place?
Explicit routes for each path
Define a route for each distinct path to a leaf page, e.g.: a book detail. This approach looks most promising at the moment.
ShellRoute
The latest addition to the go_router package, the ShellRoute widget, is designed to explicitly address issues with navigation bars and state management. However, it seems that the work is still ongoing (e.g.: issue 99124, PR 2650) and I would like to wait for the dust to settle.
Something else
There is a good chance that I have missed something obvious so please feel free to comment
Summary
A navigation 2.0 package such as go_router or beamer is certainly a good choice for anybody working on a web app. But is it worth the hassle for a mobile-only app or will I end up with a reproduction of my previous router class (nav 1.0 style with named routes?)
The verdict is still out and I will update this article as I learn more.