I'm using go_router
and trying to handle auth using redirects, so if a user isn't logged in they go to the inviteCode
screen. This all works well.
My flow is:
invite screen -> home -> profile
The profile
screen has a log out
button on it.
My problem is that when the user logs out they return to the inviteCode
screen correctly, but if they press the android back button, they end up at the home
screen which should only be access when authenticated. (Note the same happens if I add a button with context.pop()
onto that original screen)
Here's my GoRouter
config
/// Forwards diagnostic messages to the dart:developer log() API.
debugLogDiagnostics: true,
errorBuilder: (context, state) => ErrorPage(state),
initialLocation: '/',
redirect: (BuildContext context, GoRouterState state) {
User user = context.read(userStateProvider);
if (!user.isLoggedIn) {
return '/welcome/inviteCode';
} else {
return null;
}
},
routes: <RouteBase>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) {
return const HomeScreen();
},
routes: <RouteBase>[
GoRoute(
path: 'profile',
builder: (BuildContext context, GoRouterState state) {
return const ProfileScreen();
},
),
GoRoute(
path: 'welcome/inviteCode',
builder: (BuildContext context, GoRouterState state) {
return const InviteCodeScreen();
},
)
],
),
],
);
Does anyone know what I should be doing to stop this happening. It feels like a pretty common usage pattern that I'd imagine lots of other apps use with it, but I'm finding the documentation hard to follow/outdated
That is the expected behavior based on your routes hierarchy structure. GoRouter uses declarative routing (aka Flutter Navigator 2.0). Navigating to a destination using declarative routing will replace the current stack of "screens" with the stack of "screens" configured to be displayed for the destination route.
On your routes configuration the route with path "welcome/inviteCode" is a child of the route "/". When you navigate using "go" to "/welcome/inviteCode" it will build the stack of routes bellow:
|- HomeScreen
| |- InviteCodeScreen
Which means that if you "pop back" from that InviteCodeScreen
screen it will show the HomeScreen
screen, since it's the page that is "bellow" it in the stack of routes.
If you want you InviteCodeScreen
to be a root route, you shall move it up in the routes configuration hierarchy and put it at the same level as HomeScreen
:
routes: <RouteBase>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) {
return const HomeScreen();
},
routes: <RouteBase>[
GoRoute(
path: 'profile',
builder: (BuildContext context, GoRouterState state) {
return const ProfileScreen();
},
),
],
),
GoRoute(
path: '/welcome/inviteCode',
builder: (BuildContext context, GoRouterState state) {
return const InviteCodeScreen();
},
)
],
IMPORTANT: The path is now /welcome/inviteCode
instead of just welcome/inviteCode
since it is no longer a child route of /