GoRouter is a popular package for declarative routing in Flutter. It based on the Navigator 2.0 API, and supports deep linking and other common navigation scenarios, all behind an easy to use API.
If you're coming from Navigator 1.0, you'll be familiar with the concept of pushing a route to the navigation stack.
But when using GoRouter, you have two separate options:
- going to a route
- pushing a route
This article will explore the difference between the two, so that you can choose the most appropriate one on a case-by-case basis.
Build and grow in-app purchases. Glassfy’s Flutter SDK solves all the complexities and edge cases of in-app purchases and subscriptions so you don't have to. Test and build for free today by clicking here.
Declarative routing with GoRouter
To start off, let's consider a simple route hierarchy made of one top route with two sub-routes:
GoRouter( initialLocation: '/', routes: [ // top-level route GoRoute( path: '/', builder: (context, state) => const HomeScreen(), routes: [ // one sub-route GoRoute( path: 'detail', builder: (context, state) => const DetailScreen(), ), // another sub-route GoRoute( path: 'modal', pageBuilder: (context, state) => const MaterialPage( fullscreenDialog: true, child: ModalScreen(), ), ) ], ), ], )
Let's also define 3 pages for our routes:
Navigating from the top route
Now, suppose that we're in the
HomeScreen, which is just a simple page with three buttons, with callbacks defined like this:
// onPressed callback for the first button context.go('/detail'), // onPressed callback for the second button context.push('/detail'), // onPressed callback for the third button context.go('/modal'),
The first and second callback have the same target location (
/detail), and as a result they behave in the same way.
That is, in both cases we'll end up with two routes in the navigation stack (home → detail).
The difference between Go and Push
From the detail page, we can now navigate to
/modal in two different ways:
// onPressed callback for the first button context.go('/modal'), // onPressed callback for the second button context.push('/modal'),
This time the result is different:
- If we use
go, we end up with the modal page on top of the home page
- If we use
push, we end up with the modal page on top of the detail page
go jumps to the target route (
/modal) by discarding the previous route (
/modal is not a sub-route of
push always adds the target route on top of the existing one, preserving the navigation stack.
This means that once we dismiss the modal page, we navigate back to:
- the home page, if we used
- the detail page, if we used
Here's a short video showing this behavior:
And here's a gist with the full source code:
The bottom line?
go as a way to jump to a new route. This will modify the underlying navigation stack if the new route is not a sub-route of the old one.
On the other hand,
push will always push the destination route on top of the existing navigation stack.
For more info about GoRouter, you can check the API docs or head over to the old documentation site (which is a bit outdated but still an excellent resource).
New Flutter Course Now Available
I launched a brand new course that covers GoRouter in great depth, along with other important topics like state management, app architecture, testing, and much more: