methuselah
methuselah

Reputation: 13216

CanActivate causing throttling history state error

Whenever I navigate to /about page my app ends up in an infinite loop with the error Throttling history state changes to prevent the browser from hanging.

Whenever I navigate to / page my app doesn't navigate to dashboard, it just displays a blank page.

I am expecting my page to navigate to /dashboard if a token is found and /home or / when it isn't.

Furthermore, I would like the remaining pages linked below to be inaccessible (apart from dashboard), if a token is found.

How can I fix this?

app.routing.component.ts

const routes: Routes = [
  { path: 'about', component: AboutComponent, canActivate: [AuthGuard] },
  { path: 'home', component: HomeComponent },
  { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },
  { path: 'careers', component: CareersComponent },
  { path: 'contact', component: ContactComponent },
  { path: 'legal', component: LegalComponent },
  { path: 'login', component: LoginComponent },
  { path: 'press', component: PressComponent },
  { path: 'markets', component: MarketsComponent },
  { path: 'markets/:symbol', component: PriceComponent },
  { path: 'register', component: RegisterComponent },
  { path: 'status', component: StatusComponent },
  { path: 'services', component: ServicesComponent },
  { path: 'support', component: SupportComponent },
  { path: 'support/account-management', component: AccountManagementComponent },
  { path: 'support/transactions', component: TransactionsComponent },
  { path: 'support/payment-methods', component: PaymentMethodsComponent },
  { path: 'support/security', component: SecurityComponent },
  { path: 'support/task-administration', component: TaskAdministrationComponent },
  { path: 'support/wallet-services', component: WalletServicesComponent },
  { path: '**', redirectTo: '', pathMatch: 'full' },
  { path: '', component: HomeComponent },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule implements OnInit {
  constructor() { }

  ngOnInit() {
    RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled' });
  }
}

auth.guard.ts

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private authService: AuthService,
    private router: Router) {
  }

  canActivate(
    _next: ActivatedRouteSnapshot,
    _state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    if (this.authService.isLoggedIn()) {
      this.router.navigate(['dashboard']);
      if (environment.production === false) {
        console.log('Token found, redirecting to dashboard');
      }
      return true;
    } else {
      this.router.navigate(['home']);
      if (environment.production === false) {
        console.log('Token not found, redirecting to home');
      }
      return false;
    }
  }
}

auth.service.ts

@Injectable()
export class AuthService {
  constructor(private myRoute: Router) { }

  getToken() {
    return localStorage.getItem('token');
  }

  isLoggedIn() {
    return this.getToken() !== null;
  }

  logout() {
    localStorage.removeItem('token');
    this.myRoute.navigate(['login']);
  }
}

Upvotes: 1

Views: 3212

Answers (1)

Johanneke
Johanneke

Reputation: 5783

First, I think you need to put the wildcard last:

  { path: '', component: HomeComponent },
  { path: '**', redirectTo: '', pathMatch: 'full' }

Second, if you want a page to be inaccessibly depending on a token, you should add a guard on those pages.

Third, you have / mapped to the HomeComponent, so that will never redirect to the DashboardComponent.

Fourth, I believe the infinite loop is because your AuthGuard redirects to /dashboard. That path is guarded by AuthGuard, which redirects to /dashboard, etc. etc. You shouldn't redirect to a path which is guarded by the same guard that does the redirecting.

What I think you should do, is split your guards into two:

  • one guard for /home to redirect to dashboard if there is a token. This guard should not redirect to home if there is no token, because that is already the current path!
  • one guard for the /dashboard and those other paths to redirect to home if there is no token. This guard should not redirect to dashboard if there is a token!

Upvotes: 2

Related Questions