csells / go_router

The purpose of the go_router for Flutter is to use declarative routes to reduce complexity, regardless of the platform you're targeting (mobile, web, desktop), handling deep linking from Android, iOS and the web while still allowing an easy-to-use developer experience.
https://gorouter.dev
441 stars 97 forks source link

Nested navigation for tabs with their own stateful widget UI with no interdependendt data #144

Closed nyck33 closed 3 years ago

nyck33 commented 3 years ago

This had me scratching my head as the example uses the Families data. Based on that, I came up with below rough draft.

class Tab {
  Tab({required this.id, required this.tab});
  final String id;
  final ConsumerStatefulWidget tab;

  ConsumerStatefulWidget? get mytab => tab;
}

class Tabs {
  static final tabsList = [
    Tab(
      id: 'basic-info',
      tab: BasicInfoTab(), //stateful widget
    ),
    Tab(
      id: 'admins-list',
      tab: AdminsListTab(), //stateful widget
    ),
  ];
}

class TabsPage extends ConsumerStatefulWidget {
  const TabsPage({Key? key, this.selectedTab}) : super(key: key);
  final Tab? selectedTab;
  @override
  _TabsPageState createState() => _TabsPageState();
}

class _TabsPageState extends ConsumerState<TabsPage> {
  Tab? get selectedTab => widget.selectedTab;
  @override
  Widget build(BuildContext context) {
    return selectedTab!.mytab!; //myTab is the member stateful widget
  }
}
//in main
late final _router = GoRouter(
  routes: [
    GoRoute(
      path: '/settings',
      redirect: (_) => '/settings/${Tabs.tabsList[0].id}',
    ),
    GoRoute(
      path: '/settings/:tid',
      pageBuilder: (context, state) {
        var selectedTab;
        for (Tab t in Tabs.tabsList) {
          if (t.id == state.params['tid']) {
            selectedTab = t;
            break;
          }
        }
        return MaterialPage<void>(
          key: state.pageKey,
          child: TabsPage(key: state.pageKey, selectedTab: selectedTab),
        );
      },
    ),
  ],
  errorPageBuilder: (context, state) => MaterialPage<void>(
    key: state.pageKey,
    child: ErrorPage(state.error),
  ),
);

Can I get an opinion whether this is going to work and what can be improved? Ideally an example included in the repo examples would be great to have.