Skip to content

Commit

Permalink
[go_router] Nested stateful navigation with ShellRoute (flutter#2650)
Browse files Browse the repository at this point in the history
Added functionality for building route configuration with support for preserving state in nested navigators. This change introduces a new shell route class called `StatefulShellRoute`, that uses separate navigators for its child routes as well as preserving state in each navigation branch. This is convenient when for instance implementing a UI with a `BottomNavigationBar`, with a persistent navigation state for each tab (i.e. building a `Navigator` for each tab). 
An example showcasing a UI with BottomNavigationBar and StatefulShellRoute has also been added ([`stateful_shell_route.dart`](https://github.com/tolo/flutter_packages/blob/nested-persistent-navigation/packages/go_router/example/lib/stateful_shell_route.dart)). 

Other examples of using `StatefulShellRoute` are also available in these repositories: 
* [stateful_books](https://github.com/tolo/stateful_books) - A fork of the Books example of go_router.
* [stateful_navbar](https://github.com/tolo/stateful_navbar) - A clone of the Flutter Material 3 Navigation Bar example.

<br/>
Below is a short example of how a `StatefulShellRoute` can be setup:

```dart
StatefulShellRoute(
  /// Each separate stateful navigation tree (i.e. Navigator) is represented by
  /// a StatefulShellBranch, which defines the routes that will be placed on that
  /// Navigator. StatefulShellBranch also makes it possible to configure
  /// things like an (optional) Navigator key, the default location (i.e. the
  /// location the branch will be navigated to when loading it for the first time) etc.
  branches: <StatefulShellBranch>[
    StatefulShellBranch(navigatorKey: optionalNavigatorKey, routes: <RouteBase>[
      GoRoute(
        path: '/a',
        builder: (BuildContext context, GoRouterState state) =>
        const RootScreen(label: 'A'),
        routes: <RouteBase>[
          GoRoute(
            path: 'details',
            builder: (BuildContext context, GoRouterState state) =>
            const DetailsScreen(label: 'A'),
          ),
        ],
      ),
    ]),
    /// The default location of a branch will by default be the first of the
    /// configured routes. To configure a different route, provide the
    /// defaultLocation parameter.
    StatefulShellBranch(defaultLocation: '/b/detail', routes: <RouteBase>[
      GoRoute(
        path: '/b',
        builder: (BuildContext context, GoRouterState state) =>
        const RootScreen(label: 'B'),
        routes: <RouteBase>[
          GoRoute(
            path: 'details',
            builder: (BuildContext context, GoRouterState state) =>
            const DetailsScreen(label: 'B'),
          ),
        ],
      ),
    ]),
  ],
  /// Like ShellRoute, the builder builds the navigation shell around the
  /// sub-routes, but with StatefulShellRoute, this navigation shell is able to
  /// maintain the state of the Navigators for each branch. The navigation shell
  /// could for instance use a BottomNavigationBar or similar.
  builder: (BuildContext context, StatefulShellRouteState state, Widget child) =>
      ScaffoldWithNavBar(shellState: state, body: child),
)
```

This fixes issue flutter/flutter#99124.
It also (at least partially) addresses flutter/flutter#112267.
  • Loading branch information
tolo committed May 22, 2023
1 parent 10689c2 commit cc96af0
Showing 0 changed files with 0 additions and 0 deletions.

0 comments on commit cc96af0

Please sign in to comment.