Shell route reverts back to default

I my app I use riverpod to provide the routing (ShellRoute) to my page, it reverts back to the default route, anyone have a sharp eye as to where my mistake lie?
My routes

class AppRoutes {
  static final router = GoRouter(
      routerNeglect: true,
      initialLocation: SplashPage.route,
      navigatorKey: Utils.mainNav,
      routes: [
        GoRoute(
          parentNavigatorKey: Utils.mainNav,
          path: SplashPage.route,
          builder: (context, state) {
            return const SplashPage();
          },
        ),
        GoRoute(
          parentNavigatorKey: Utils.mainNav,
          path: LoadingPage.route,
          builder: (context, state) {
            return const LoadingPage();
          },
        ),
        ShellRoute(
            navigatorKey: Utils.tabNav,
            builder: (context, state, child) {
              return MainPage(child: child);
            },
            routes: [
              GoRoute(
                parentNavigatorKey: Utils.tabNav,
                path: HomePage.route,
                pageBuilder: (context, state) {
                  return const NoTransitionPage(
                    child: HomePage(),
                  );
                },
              ),
              GoRoute(
                parentNavigatorKey: Utils.tabNav,
                path: RoomsPage.route,
                pageBuilder: (context, state) {
                  return const NoTransitionPage(
                    child: RoomsPage(),
                  );
                },
              ),
              GoRoute(
                parentNavigatorKey: Utils.tabNav,
                path: DevicesPage.route,
                pageBuilder: (context, state) {
                  return const NoTransitionPage(
                    child: DevicesPage(),
                  );
                },
              ),
              GoRoute(
                parentNavigatorKey: Utils.tabNav,
                path: SettingsPage.route,
                pageBuilder: (context, state) {
                  return const NoTransitionPage(
                    child: SettingsPage(),
                  );
                },
              ),
            ]),
      ]);
}

Provider

final bottomBarMenuProvider =
    StateNotifierProvider<BottomBarMenuViewModel, List<BottomBarMenuItemModel>>(
        (ref) {
  final navItems = ref.read(bottomBarRepositoryProvider).getBottomBarNavItems();
  return BottomBarMenuViewModel(navItems, ref);
});

final bottomBarRepositoryProvider = Provider((ref) {
  return BottomMenuBarRepository();
});

Menu Repository

class BottomMenuBarRepository {
  List<BottomBarMenuItemModel> getBottomBarNavItems() {
    return const [
      BottomBarMenuItemModel(
        iconOption: Icons.home,
        route: HomePage.route,
        isSelected: true,
      ),
      BottomBarMenuItemModel(
        iconOption: Icons.door_back_door,
        route: RoomsPage.route,
      ),
      BottomBarMenuItemModel(
        iconOption: Icons.devices,
        route: DevicesPage.route,
      ),
      BottomBarMenuItemModel(
        iconOption: Icons.build,
        route: SettingsPage.route,
      )
    ];
  }
}

Bottom Menu

class HomeAutomationBottomMenu extends ConsumerWidget {
  const HomeAutomationBottomMenu({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final menuItems = ref.watch(bottomBarMenuProvider);

    return Container(
      padding: AppThemeStyles.xsmallPadding,
      child: Flex(
          direction: Axis.horizontal,
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: menuItems.map((e) {
            return Container(
              margin: const EdgeInsets.only(
                bottom: AppThemeStyles.smallSize,
              ),
              child: IconButton(
                  onPressed: () {
                    ref.read(bottomBarMenuProvider.notifier).selectedItem(e);
                    debugPrint(e.route);
                  },
                  icon: Icon(
                    e.iconOption,
                    color: e.isSelected
                        ? Theme.of(context).colorScheme.primary
                        : Theme.of(context).iconTheme.color,
                  )),
            );
          }).toList()),
    );
  }
}

Main Page

class MainPage extends StatelessWidget {
  final Widget child;
  const MainPage({super.key, required this.child});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Flex(
        direction: Axis.vertical,
        children: [
          Expanded(
            child: SafeArea(child: child),
          ),
          const HomeAutomationBottomMenu()
        ],
      ),
    );
  }
}

menu

Whenever you call your bottomBarMenuProvider it calls the bottomBarRepositoryProvider and since you’re not mutating your repository your getBottomBarNavItems is always returning the default values which sets the home as selected by default.


You can verify that by setting another tab to default. The same issue will occur but with that other tab.

1 Like

I do update my GoRouter to the selected route in

class BottomBarViewModel extends StateNotifier<List<BottomBarMenuItemModel>> {
  final Ref ref;
  BottomBarViewModel(super.state, this.ref);

  void selectedItem(BottomBarMenuItemModel selectedItem) {
    state = [
      for (var item in state) item.copyWith(isSelected: selectedItem == item)
    ];

    GoRouter.of(Utils.tabNav.currentContext!).go(selectedItem.route);
  }

}

Sorry I did omit this from the first post