How to use a parameterized route as the root of a StatefulShellRoute with GoRoute
Asked Answered
N

2

6

I have a flutter app that I wanted to add stateful navigation to. I wanted to have it so that you can look at the list of "Foos" and then choose a Foo to look at. On the Foo detail page I wanted to have 3 tabs and have stateful navigation on those three tabs. The urls would look something like this:

  • /foo
    • /:id
      • /pageA
      • /pageB
      • /pageC

I was following this example to incorporate go_router's StatefulShellRoute. The example looked exactly like I wanted, except when I added it to my app with the parameterized route, I get this error:

The default location of a StatefulShellBranch cannot be a parameterized route

The error seems to imply that I can't start the stateful branch on a page that is parameterized, but that's where I want my nested navigation with tabs to start. Is there a way around this or another way to accomplish this?

Here's the router I was trying to setup:

final GoRouter _router = GoRouter(
  navigatorKey: _rootNavigatorKey,
  routes: <RouteBase>[
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) {
        return MyHomePage();
      },
      routes: [
        GoRoute(
            path: 'foo',
            builder: (BuildContext context, GoRouterState state) {
              return const FooListScreen();
            },
            routes: [
              StatefulShellRoute.indexedStack(
                  builder: (context, state, navigationShell) {
                    return Scaffold(body: Center(child: Text("fix this scaffold")));
                  },
                  branches: [
                    StatefulShellBranch(
                        navigatorKey: _fooNavigatorKey,
                        routes: [
                          GoRoute(
                              name: "fooDetails",
                              path: ":id",
                              builder: (context, state) => FooDetailScreen(
                                  id: int.parse(
                                      state.pathParameters['id'] ?? "0"))),
                        ]),
                  ]),
            ]),
      ],
    ),
  ],
);

I'm using Flutter 3.7.11 and go_router 8.0.5

Nipissing answered 21/6, 2023 at 23:12 Comment(0)
K
2

one workaround could be to add a dummy route before your parameterized route, see this example:

final GoRouter _router = GoRouter(
  navigatorKey: _rootNavigatorKey,
  routes: <RouteBase>[
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) {
        return MyHomePage();
      },
      routes: [
        GoRoute(
            path: 'foo',
            builder: (BuildContext context, GoRouterState state) {
              return const FooListScreen();
            },
            routes: [
              StatefulShellRoute.indexedStack(
                  builder: (context, state, navigationShell) {
                    return Scaffold(body: Center(child: Text("fix this scaffold")));
                  },
                  branches: [
                    StatefulShellBranch(
                        navigatorKey: _fooNavigatorKey,
                        routes: [

                          GoRoute(
                              name: "dummyRoute",
                              path: "/dummy",
                              builder: (context, state) => DummyScreen(),
    ),
                          GoRoute(
                              name: "fooDetails",
                              path: ":id",
                              builder: (context, state) => FooDetailScreen(
                                  id: int.parse(
                                      state.pathParameters['id'] ?? "0"))),
                        ]),
                  ]),
            ]),
      ],
    ),
  ],
);
Kalinin answered 22/9, 2023 at 12:42 Comment(1)
Worked in my case, thanks!Graze
A
1

You can audoredirect your route with params:

StatefulShellBranch(
  navigatorKey: shellUniqeKey,
  routes: [
    GoRoute(
      name: "fooDetails",
      path: "/fooDetails",
      redirect: (context, state) =>
          '/fooDetails/${state.pathParameters['id']}',
      routes: [
        GoRoute(
          path: ':id',
          builder: (context, state) => const FooDetailScreen(id: state.pathParameters['id']),
        ),
      ],
    ),
  ],
),
Adamandeve answered 9/10, 2023 at 8:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.