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.
sponsor

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