Search code examples
flutterflutter-go-router

Using go_router package in a flutter app with a statefulShellRoute, how to navigate to routes outside of the shell?


I have implemented go_router statefulShellRoute for bottomNavigationBar to have nested routes in a flutter app.

But I also have pages I want to be outside of the statefulShellRoute (outside bottom nav bar), i have these routes defined in GoRouter outside of the shell routes list but when I navigate to them using context.push(), as expected I can still see the Bottom Navigation Bar since it pushes the new screen onto the nested navigation stack.

If I use context.go(), even though I can reach the page and make the bottom nav bar disappear, I can't go back now since the previous route was replaced.

How can I push a route outside of the bottom navigation bar shell and still have the ability to come back?


Solution

  • Was searching for the same question before. Here is the answer for future searchers: you need to assign parentNavigatorKey for your route to be pushed over shell route. Example from go_router repo (pay attention to _rootNavigatorKey):

      final GoRouter _router = GoRouter(
        navigatorKey: _rootNavigatorKey,
        initialLocation: '/a',
        debugLogDiagnostics: true,
        routes: <RouteBase>[
          /// Application shell
          ShellRoute(
            navigatorKey: _shellNavigatorKey,
            builder: (BuildContext context, GoRouterState state, Widget child) {
              return ScaffoldWithNavBar(child: child);
            },
            routes: <RouteBase>[
              /// The first screen to display in the bottom navigation bar.
              GoRoute(
                path: '/a',
                builder: (BuildContext context, GoRouterState state) {
                  return const ScreenA();
                },
                routes: <RouteBase>[
                  // The details screen to display stacked on the inner Navigator.
                  // This will cover screen A but not the application shell.
                  GoRoute(
                    path: 'details',
                    builder: (BuildContext context, GoRouterState state) {
                      return const DetailsScreen(label: 'A');
                    },
                  ),
                ],
              ),
    
              /// Displayed when the second item in the the bottom navigation bar is
              /// selected.
              GoRoute(
                path: '/b',
                builder: (BuildContext context, GoRouterState state) {
                  return const ScreenB();
                },
                routes: <RouteBase>[
                  /// Same as "/a/details", but displayed on the root Navigator by
                  /// specifying [parentNavigatorKey]. This will cover both screen B
                  /// and the application shell.
                  GoRoute(
                    path: 'details',
                    parentNavigatorKey: _rootNavigatorKey,
                    builder: (BuildContext context, GoRouterState state) {
                      return const DetailsScreen(label: 'B');
                    },
                  ),
                ],
              ),