go_router

Declarative Routing

go_router is governed by a set of routes which you specify as part of the GoRouter constructor:

class App extends StatelessWidget {
  ...
  final _router = GoRouter(
    routes: [
      GoRoute(
        path: '/',
        builder: (context, state) => const Page1Screen(),
      ),
      GoRoute(
        path: '/page2',
        builder: (context, state) => const Page2Screen(),
      ),
    ],
  );
}

In this case, we've defined two routes. Each route path will be matched against the location to which the user is navigating. Only a single route can be matched, specifically the one whose path matches the entire location (and so it doesn't matter in which order you list your routes). The path will be matched in a case-insensitive way, although the case for parameters will be preserved.

In addition to the path, each route will typically have a builder function, which is responsible for building the Widget that is to take up the entire screen of your app. The default transition will be used between pages depending on the type of app you've put at the top of your widget tree, e.g. the use of MaterialApp will cause go_router to use the MaterialPage transitions.

Router state#

While it's not used in the snippet above, the builder function are passed a state object, which is an instance of the GoRouterState class that contains some useful information:

GoRouterState propertydescriptionexample 1example 2
locationlocation of the full route, including query params/login?from=/family/f2/family/f2/person/p1
subloclocation of this sub-route w/o query params/login/family/f2
nameroute nameloginfamily
pathroute path/loginfamily/:fid
fullpathfull path to this sub-route/login/family/:fid
paramsparams extracted from the location{}{'fid': 'f2'}
queryParamsoptional params from the end of the location{'from': '/family/f1'}{}
extraoptional object paramnullnull
errorException associated with this sub-route, if anyException('404')...
pageKeyunique key for this sub-routeValueKey('/login')ValueKey('/family/:fid')

The state object is useful for passing parameters to parameterized routes and for redirection. Not all of the state parameters will be set every time. In general, GoRouterState defines a superset of the potential current state of a GoRouter instance. For example, the error parameter will only be set if there's an error.

Initialization#

With a list of routes, you can create an instance of a GoRouter, which itself provides the objects you need to call the MaterialApp.router constructor (or the CupertinoApp.router constructor):

class App extends StatelessWidget {
  App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => MaterialApp.router(
        routeInformationParser: _router.routeInformationParser,
        routerDelegate: _router.routerDelegate,
      );

  final _router = GoRouter(routes: ...);
}

With the router in place, your app can now navigate between pages.

Error handling#

By default, go_router comes with default error screens for both MaterialApp and CupertinoApp as well as a default error screen in the case that you're using neither. You can replace the default error screen by setting the errorBuilder parameter of the GoRouter:

class App extends StatelessWidget {
  ...
  final _router = GoRouter(
    ...
    errorBuilder: (context, state) => ErrorScreen(state.error),
  );
}

The error screen, whether it's provided by you or go_router, will be used in case a location doesn't match a route, more than one route is found for a given location or if any of the builder functions throws an exception.

Deep Linking#

Flutter defines "deep linking" as "opening a URL displays that screen in your app." Anything that's listed as a GoRoute can be accessed via deep linking across Android, iOS and the web. Support works out of the box for the web, of course, via the address bar, but requires additional configuration for Android and iOS as described in the Flutter docs.