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

Redirection loop exception #334

Closed diegopq closed 2 years ago

diegopq commented 2 years ago

I want to handle the redirection when a user authenticates and also if the user decides to skip the login, I use bloc as a state manager. The redirection works only if the user is authenticated but it doesn't work when the user decides to skip the login and it throws me a "redirect loop" exception. what the exception tells me is that it goes from login to home and then to login, the code inside the redirect callback is as follows:

redirect: (state) {

      //indicates if the user is authenticated or not
      final userAutheticated =
          _authBloc.state.status == AppAuthStatus.authenticated &&
              _authBloc.state.userData.name.isNotEmpty &&
              _authBloc.state.userId.isNotEmpty ;

      if (_authBloc.state.skipLogin && state.location != '/home') {
        //if the login is skipped, it redirects to home
        return '/home';
      } else {
        //if it is in the initial route
        final isInLoginPage = state.location == '/login';

        //if the user is not authenticated and is not in the login route, it returns him to the login
        if (!userAutheticated) return isInLoginPage ? null : '/login';

       //If the user is authenticated but is on the login page, it sends him to the home
        if (isInLoginPage) return '/home';
      }
      return null;
    },
    refreshListenable: GoRouterRefreshStream(_authBloc.stream),

This is the exception that is thrown:

flutter: ══╡ EXCEPTION CAUGHT BY GOROUTER ╞══════════════════════════════════════════════════════════════════
flutter: The following _Exception was thrown Exception during GoRouter navigation:
flutter: Exception: redirect loop detected: /login => /home => /login
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0      GoRouterDelegate._getLocRouteMatchesWithRedirects.redirected
package:go_router/src/go_router_delegate.dart:299
flutter: #1      GoRouterDelegate._getLocRouteMatchesWithRedirects
package:go_router/src/go_router_delegate.dart:318
flutter: #2      GoRouterDelegate._go
package:go_router/src/go_router_delegate.dart:245
flutter: #3      GoRouterDelegate.refresh
package:go_router/src/go_router_delegate.dart:187
flutter: #4      ChangeNotifier.notifyListeners
package:flutter/…/foundation/change_notifier.dart:308
flutter: #5      new GoRouterRefreshStream.<anonymous closure>
package:go_router/src/go_router_refresh_stream.dart:29
flutter: (elided 25 frames from dart:async)
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════

I don't know why it tries to redirect to login when login is skipped

leoshusar commented 2 years ago

User goes to /login. Skips authentication, it redirects him to /home. Then if (_authBloc.state.skipLogin && state.location != '/home') is if (true && false), so the else block runs.

final isInLoginPage = state.location == '/login'; is false, he's not on /login now, he was redirected to /home. Lastly if (!userAutheticated) return isInLoginPage ? null : '/login'; is if (!false) return false ? null : /login - this part redirects him back.

Did I explain it good enough?

diegopq commented 2 years ago

User goes to /login. Skips authentication, it redirects him to /home. Then if (_authBloc.state.skipLogin && state.location != '/home') is if (true && false), so the else block runs.

final isInLoginPage = state.location == '/login'; is false, he's not on /login now, he was redirected to /home. Lastly if (!userAutheticated) return isInLoginPage ? null : '/login'; is if (!false) return false ? null : /login - this part redirects him back.

Did I explain it good enough?

yes