GoRouter: Navigation 2.0 in Flutter

Aditya Mhatre
Stackademic
Published in
4 min readJan 2, 2024

--

Introduction 🌅

Flutter is a popular framework for building cross-platform applications with beautiful UI and great performance. However, one of the challenges that Flutter developers face is how to handle navigation in their apps. Navigation is the process of moving from one screen to another, passing data between them, and managing the app’s history stack. Navigation is essential for creating a good user experience and a logical flow of information.

Navigation in Flutter 🔗

Flutter provides two ways to navigate between screens: imperative and declarative. Imperative navigation is the traditional way of using the Navigator class and its methods, such as push, pop, replace , etc. Imperative navigation gives you full control over the navigation logic, but it also requires you to write a lot of boilerplate code and handle edge cases manually. For example, you need to manage the back button behavior, deep linking, web URL routing, nested navigation, etc.

Declarative navigation is a newer way of using the `Navigator` class and its widgets, such as Navigator, RouteInformationParser, RouterDelegate, etc. Declarative navigation is based on the concept of Navigation 2.0, which is a set of APIs that Flutter introduced in version 1.22 to support complex navigation scenarios. Declarative navigation allows you to define your app’s navigation structure as a state and let Flutter handle the navigation logic for you. For example, Flutter can automatically update the browser URL, handle the back button, restore the app state, etc.

Navigation 2.0 🖇️

Navigation 2.0 is a major improvement over the previous navigation system, but it also comes with a steep learning curve and a lot of complexity. Navigation 2.0 requires you to implement several classes and widgets, such as RouteInformationProvider, RouteInformationParser, RouterDelegate, PageRoute, etc. You also need to understand how these classes and widgets interact with each other and with the platform-specific features, such as the browser URL, the app bar, the system back button, etc. Moreover, you need to handle the transitions, animations, and modals for each route.

Navigation 2.0 is powerful and flexible, but it is also verbose and confusing. Many developers find it hard to grasp and use Navigation 2.0 in their apps. That’s why there are several packages that aim to simplify and abstract the Navigation 2.0 APIs and provide a more intuitive and easy-to-use way of navigating in Flutter. One of these packages is GoRouter.

GoRouter 🏃🏻‍♂️

GoRouter is a simple and elegant package for declarative navigation in Flutter. It is created by Chris Sells, a product manager at Google and a Flutter enthusiast. GoRouter is based on Navigation 2.0, but it hides all the complexity and boilerplate behind a simple and expressive API. GoRouter allows you to define your app’s routes as a list of GoRoute objects, each with a name, a path, a page builder, and optionally some parameters, guards, and redirects. GoRouter also provides some convenient widgets and methods to navigate between the routes, such as GoRouter.of(context), context.go(), GoBackButton, GoRouterLink, etc.

GoRouter is designed to be easy to use, understand, and maintain. It supports all the features that you would expect from a modern navigation system, such as:

Named routes with parameters and query strings

Nested routes with tabs and drawers

Dynamic routes with path variables and wildcards

Route guards and redirects

Transitions and animations

Deep linking and web URL routing

App state restoration

Error handling and fallback routes

Customizable app bar and back button

Installation ⚙️

Getting started with GoRouter is a breeze. Begin by adding the package to your pubspec.yaml file:

dependencies:
go_router: ^2.4.0

After updating your dependencies, run:

flutter pub get

Using GoRouter:🔨

To use GoRouter in your app, you need to follow these steps:

Define Routes

Define your app’s routes as a list of GoRoute objects. Each GoRoute object has a name, a path, and a pageBuilder function that returns a Page widget. You can also specify some optional parameters, such as params, guards, redirects, transitionsBuilder

final _routes = [
GoRoute(
name: 'home',
path: '/',
pageBuilder: (context, state) => MaterialPage(
key: state.pageKey,
child: HomePage(),
),
),
GoRoute(
name: 'settings',
path: '/settings',
pageBuilder: (context, state) => MaterialPage(
key: state.pageKey,
child: SettingsPage(),
),
),
];

GoRouter Object:

Create a GoRouter object and pass it the list of routes and an optional errorPageBuilder function that returns a Page widget for handling errors.

final _router = GoRouter(
routes: _routes,
errorPageBuilder: (context, state) => MaterialPage(
key: state.pageKey,
child: ErrorPage(state.error),
),
);

Integrate in MaterialApp

Use the GoRouter object as the routerDelegate of your MaterialApp widget. You can also use the GoRouter.urlStrategy as the routeInformationParser to enable web URL routing.

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerDelegate: _router,
routeInformationParser: _router.urlStrategy,
);
}
}

Use in WIdget Tree

Use the GoRouter.of(context) method to access the GoRouter object in your widgets and call its methods, such as go, push, replace, refresh, etc. to navigate between the routes. You can also use the context.go() extension method for convenience.

class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
context.go('/details/42');
},
child: Text('Go to details'),
),
),
);
}
}

Conclusion 📰

GoRouter is designed to be easy to use, understand, and maintain. It supports all the features that you would expect from a modern navigation system, such as named routes, nested routes, dynamic routes, route guards, redirects, transitions, animations, deep linking, web URL routing, app state restoration, error handling, and fallback routes. GoRouter is also customizable and extensible, allowing you to create your own widgets, transitions, and strategies.

Thanks for reading. If you found this article to be helpful please share it with your friends.

Stackademic

Thank you for reading until the end. Before you go:

  • Please consider clapping and following the writer! 👏
  • Follow us on Twitter(X), LinkedIn, and YouTube.
  • Visit Stackademic.com to find out more about how we are democratizing free programming education around the world.

--

--

Flutter Developer 🩵 • Finding my way through amazements of Tech.