1

Problem: I’m using GoRouter with a GoRouterRefreshStream that listens to my AuthCubit.stream (Cubit emits states like Authenticated, UnAuthenticated, etc.).

Everything works fine when logging in or navigating between screens, the router reacts correctly to auth state changes. But when I press logout, the app stays on the protected page (ProfileScreen) instead of redirecting to Home or Login.

After pressing logout: -The Cubit emits UnAuthenticated -The stream listener calls notifyListeners()

But the redirect doesn’t run, and I’m still stuck on /profile. If I manually add context.go(Routes.homeScreen) inside the button, it works, but I’d like this to happen automatically via GoRouter redirect, not manually in the UI.

i have tried even simple IF statement:

if (authCubit.state is! Authenticated) {
  return Routes.homeScreen;
}

and not working :(

My router:

final _rootNavigatorKey = GlobalKey<NavigatorState>();
final _shellNavigatorKey = GlobalKey<NavigatorState>();

GoRouter buildRouter(AuthCubit authCubit) {
  return GoRouter(
    navigatorKey: _rootNavigatorKey,
    initialLocation: Routes.homeScreen,
    refreshListenable: GoRouterRefreshStream(authCubit.stream),
    redirect: (context, state) {
      final s = authCubit.state;
      final loc = state.matchedLocation;

      final isAuthed = s is Authenticated;
      final emailNotVerified = s is EmailNotVerified;
      final needsCompletion = s is AuthNeedsCompletion;
      final isLoading = s is AuthLoading;

      if (isLoading) return null;

      final atLoginOrRegister = loc == Routes.loginScreen || loc == Routes.registerScreen;
      final atVerify = loc == Routes.verifyEmailScreen;
      final atComplete = loc == Routes.authCompleteScreen;
      final atAuthFlow = atLoginOrRegister || atVerify || atComplete;

      final atProfile = loc == Routes.profileScreen;
      final wantsProtected = loc.startsWith(Routes.profileScreen);

      if (authCubit.state is! Authenticated && state.uri.path == Routes.profileScreen) {
        return Routes.homeScreen;
      }

      if (emailNotVerified && !atVerify) {
        return Routes.verifyEmailScreen;
      }

      if (needsCompletion && !atComplete) {
        return Routes.authCompleteScreen;
      }

      if (!isAuthed && wantsProtected) {
        return Routes.loginScreen;
      }

      if (isAuthed && atAuthFlow && !atProfile) {
        return Routes.profileScreen;
      }

      return null;
    },
    routes: [
      GoRoute(
        parentNavigatorKey: _rootNavigatorKey,
        path: Routes.loginScreen,
        builder: (context, state) {
          final extras = state.extra as Map<String, dynamic>?;
          final token = extras?['token'] ?? 0;

          return LoginScreen(
            key: ValueKey('login-$token'),
            togglePages: () => context.replace(Routes.registerScreen),
            extras: extras,
          );
        },
        routes: [GoRoute(path: 'forgotPassword', builder: (context, state) => const ForgottenPasswordScreen())],
      ),
      GoRoute(
        parentNavigatorKey: _rootNavigatorKey,
        path: Routes.registerScreen,
        builder: (context, state) => RegisterScreen(togglePages: () => context.replace(Routes.loginScreen)),
      ),
      GoRoute(
        path: Routes.profileScreen,
        parentNavigatorKey: _rootNavigatorKey,
        builder: (context, state) => const ProfileScreen(),
      ),
      GoRoute(
        path: Routes.authCompleteScreen,
        parentNavigatorKey: _rootNavigatorKey,
        builder: (context, state) => const AuthCompleteScreen(),
      ),
      GoRoute(
        path: Routes.verifyEmailScreen,
        parentNavigatorKey: _rootNavigatorKey,
        builder: (context, state) => const EmailVerifyScreen(),
      ),
      StatefulShellRoute.indexedStack(
        parentNavigatorKey: _rootNavigatorKey,
        builder: (context, state, navigationShell) => MainHomeScreen(navigationShell: navigationShell),
        branches: [
          StatefulShellBranch(
            navigatorKey: _shellNavigatorKey,
            routes: [GoRoute(path: Routes.homeScreen, builder: (context, state) => const HomeScreen())],
          ),
          StatefulShellBranch(
            routes: [GoRoute(path: Routes.leagueScreen, builder: (context, state) => const LeagueScreen())],
          ),
          StatefulShellBranch(
            routes: [GoRoute(path: Routes.newsScreen, builder: (context, state) => const NewsScreen())],
          ),
          StatefulShellBranch(
            routes: [GoRoute(path: Routes.menuScreen, builder: (context, state) => const MenuScreen())],
          ),
        ],
      ),
    ],
    debugLogDiagnostics: true,
  );
}

My logout in authCubit:

  Future<void> logout() async {
    emit(AuthLoading());
    await authRepo.logout();
    emit(UnAuthenticated());
  }

My routes:

class Routes {
  static const loginScreen = '/login';
  static const forgotPasswordScreen = '/login/forgotPassword';
  static const registerScreen = '/register';
  static const verifyEmailScreen = '/verifyEmail';
  static const authCompleteScreen = '/authComplete';
  static const profileScreen = '/profile';

  static const appShell = '/app';
  static const homeScreen = '$appShell/home';
  static const leagueScreen = '$appShell/league';
  static const newsScreen = '$appShell/news';
  static const menuScreen = '$appShell/menu';
  static const settingsScreen = '$appShell/settings';
}

1 Answer 1

-1

Try adding this code in the redirect callback:

final atLoginScreen = loc = Routes.loginScreen;

if (!atLoginScreen && (authCubit.state is UnAuthenticated)) {

    return Routes.loginScreen;    

   }
Sign up to request clarification or add additional context in comments.

1 Comment

still nothing :( [GoRouter] pushing /login [GoRouter] redirecting to RouteMatchList#f1af1(uri: /profile, matches: [RouteMatch#7b0ed(route: GoRoute#7196e(parentNavKey: [LabeledGlobalKey<NavigatorState>#8d08e], name: null, path: "/profile"))]) D/WindowOnBackDispatcher(11225): setTopOnBackInvokedCallback (unwrapped): io.flutter.embedding.android.FlutterActivity$1@1bf64e1 D/FirebaseAuth(11225): Notifying id token listeners about a sign-out event. D/FirebaseAuth(11225): Notifying auth state listeners about a sign-out event. no redirect after logout,when i manually go login, the acct. is logge

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.