I’m using Go Router 6.2.0 with Flutter 3.7.3
Problem: I want to navigate to the shell route when a user is logged in and the login page when no one is logged in.
What developers usually do is redirect the route to another one when user is logged in but I can’t redirect the route to a shell route because I don’t know how
I have the 2 routes in my GoRouter, 1 is the Login route for the login page, in my login page I’m doing this to check for auth then go to the another route accordingly:
Scaffold(
body: StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
final user = snapshot.data;
if (user != null) {
GoRouter.of(context).go(NavigationRailScreen.routeName);
}
}
return Center(
child: SizedBox(
width: 400,
child: ui.SignInScreen(
providers: [ui.EmailAuthProvider()],
actions: [
ui.AuthStateChangeAction<ui.SignedIn>((context, state) {
GoRouter.of(context).go(NavigationRailScreen.routeName);
}),
],
),
),
);
}),
);
The second route is a NavigationRail which has all the rest of my routes
final GlobalKey<NavigatorState> _rootNavigator = GlobalKey(debugLabel: 'root');
final GlobalKey<NavigatorState> _shellNavigator =
GlobalKey(debugLabel: 'shell');
GoRouter router = GoRouter(
navigatorKey: _rootNavigator,
initialLocation: '/',
routes: [
GoRoute(
parentNavigatorKey: _rootNavigator,
path: '/',
name: 'login',
builder: (context, state) => AppLoginScreen(key: state.pageKey),
),
ShellRoute(
navigatorKey: _shellNavigator,
builder: (context, state, child) =>
NavigationRailScreen(key: state.pageKey, child: child),
routes: [
GoRoute(
path: '/',
name: HomeScreen.routeName,
pageBuilder: (context, state) {
return NoTransitionPage(child: HomeScreen(key: state.pageKey));
},
),
GoRoute(
path: '/restaurants',
name: RestaurantsScreen.routeName,
pageBuilder: (context, state) {
return NoTransitionPage(
child: RestaurantsScreen(key: state.pageKey));
},
routes: [
GoRoute(
parentNavigatorKey: _shellNavigator,
path: ':id',
name: RestaurantDetailsScreen.routeName,
pageBuilder: (context, state) {
final String id = state.params['id'] as String;
return NoTransitionPage(
child:
RestaurantDetailsScreen(id: id, key: state.pageKey),
);
},
routes: [
GoRoute(
parentNavigatorKey: _shellNavigator,
path: AddRestaurantReviewScreen.routeName,
name: AddRestaurantReviewScreen.routeName,
pageBuilder: (context, state) {
final String id = state.params['id'] as String;
return NoTransitionPage(
child: AddRestaurantReviewScreen(
key: state.pageKey, id: id),
);
},
),
GoRoute(
name: MenuItemsScreen.routeName,
path: MenuItemsScreen.routeName,
pageBuilder: (context, state) {
return NoTransitionPage(
child: MenuItemsScreen(
key: state.pageKey, id: state.params['id']!),
);
},
routes: [
GoRoute(
name: MenuItemDetailsScreen.routeName,
path: ':menuItemId',
pageBuilder: (context, state) {
final String id =
state.params['menuItemId'] as String;
final String restaurantId =
state.params['id'] as String;
return NoTransitionPage(
child: MenuItemDetailsScreen(
key: state.pageKey,
id: id,
restaurantId: restaurantId,
),
);
},
routes: [
GoRoute(
name: AddMenuItemReviewScreen.routeName,
path: AddMenuItemReviewScreen.routeName,
pageBuilder: (context, state) {
final String id =
state.params['menuItemId'] as String;
final String restaurantId =
state.params['id'] as String;
return NoTransitionPage(
child: AddMenuItemReviewScreen(
key: state.pageKey,
id: id,
restaurantId: restaurantId,
));
})
]),
]),
],
),
]),
GoRoute(
path: '/profile',
name: UserProfileScreen.routeName,
pageBuilder: (context, state) {
return NoTransitionPage(
child: UserProfileScreen(key: state.pageKey));
},
)
])
],
errorBuilder: (context, state) => RouteErrorScreen(
errorMsg: state.error.toString(),
key: state.pageKey,
),
);
2
Answers
To Navigate to the shell route, the code is given bellow replace the location with your route name
For Handling the authentication i use the redirect method of go router
in which emit the state of current appstatus.
Main screen
I spent several hours trying to resolve this problem, I don’t think it is possible to navigate to a shell route at the moment with GoRoute but however I wa able to find a way that works for me base on the project I am working on. Kindly checkout the code below:
First of all, I added my bottom navigation bar to my route constants.
Secondly, I created the BottomNavigationScreen.
Thirdly, I defined my shell routes and noticed I also added the BottomNavigationScreen among the routes and gave it and initial screen to display. This is the trick I used.