Reputation: 560
For some strange reason, only for certain routes, Angular Router is redirecting the user back to the base url.
Sounds like a problem with my app-routing.module.ts right?
Well this is where the strange issues start.
Strange Issue #1
Only happens when trying to navigate to /leaderboard
and to /achievements
but not on /team-view
Strange Issue #2
If I make a change to the code OR simply refresh the page, the problems are now resolved and I can now reach both /leaderboard
and /achievements
without any problems. If I log out and log back in, the problem returns.
Strange Issue #3
There are no console errors or any form of error aside from the page just flickering very quickly and redirecting me back to the /
route (which is the Dashboard Component
loads`)
Routes:
const routes: Routes = [
{
path: '',
pathMatch: 'full',
component: DashboardComponent,
canActivate: [LoggedInGuard],
},
{
path: 'team-view',
component: TeamViewComponent,
canActivate: [LoggedInGuard],
},
{
path: 'settings',
component: SettingsComponent,
canActivate: [LoggedInGuard],
},
{
path: 'leaderboard',
component: LeaderboardComponent,
canActivate: [LoggedInGuard],
},
{
path: 'achievements',
component: AchievementsComponent,
canActivate: [LoggedInGuard],
},
{ path: 'register', component: RegisterComponent },
{ path: 'login', component: LoginComponent },
];
Header Code:
<div class="menu-wrapper desktop-menu">
<span class="menu-item" routerLinkActive="menu-item-active" [routerLinkActiveOptions]="{ exact: true }" routerLink="/">Dashboard</span>
<span class="menu-item" routerLinkActive="menu-item-active" [routerLinkActiveOptions]="{ exact: true }" routerLink="/leaderboard">Leaderboard</span>
<span class="menu-item" routerLinkActive="menu-item-active" [routerLinkActiveOptions]="{ exact: true }" routerLink="/achievements">Achievements</span>
<span class="menu-item" routerLinkActive="menu-item-active" [routerLinkActiveOptions]="{ exact: true }" routerLink="/team-view">My Team</span>
<span class="menu-item" routerLinkActive="menu-item-active" (click)="ToggleNotifications()"><mat-icon matBadge="4">notifications</mat-icon></span>
<span class="menu-item" routerLinkActive="menu-item-active" (click)="SignOut()"><mat-icon>logout</mat-icon></span>
</div>
LoggedInGuard:
@Injectable()
export class LoggedInGuard implements CanActivate {
constructor(private router: Router) {}
canActivate(): Observable<boolean> | Promise<boolean> | boolean {
const isLoggedIn = localStorage.getItem('jwt') !== null;
if (!isLoggedIn) {
console.log('Returning to login screen');
this.router.navigateByUrl('login');
}
return isLoggedIn;
}
}
I also noticed some weird logging in the Angular Routing that seems to indicate that Angular Router is forcing a redirect but I don't know why?:
GuardsCheckEnd(id: 11, url: '/', urlAfterRedirects: '/', state: Route(url:'', path:'') { Route(url:'', path:'') } , shouldActivate: true)
Upvotes: 4
Views: 5257
Reputation: 11
This is really more appropriate as a comment, but when I've seen flickering in a front end app like that it was due to one of two things:
I know it's not much of an answer, but I would recommend double checking the leaderboard and achievements components. If possible maybe add a log statement detailing component state. Any shared logic or sub-components seem like a good candidate for debugging.
If you haven't all ready, try opening dev tools and monitoring the network tab just to rule out the redirect option.
Upvotes: 1
Reputation: 6225
What happens with your jwt token after you refresh? Maybe you lose jwt during some process?
But from your description seems like CanActivate
kicks in forces you to login
where, perhaps, we find that user is logged in and login
component by default moves you to /
.
canActivate
should always return boolean true/false, but here we just naviage user away:
if (!isLoggedIn) {
console.log('Returning to login screen');
this.router.navigateByUrl('login');
}
@Injectable()
export class LoggedInGuard implements CanActivate {
constructor(private router: Router) {}
canActivate(): Observable<boolean> | Promise<boolean> | boolean {
const isLoggedIn = localStorage.getItem('jwt') !== null;
if (!isLoggedIn) {
console.log('Returning to login screen');
this.router.navigateByUrl('login');
return false;
} else {
return true;
}
}
}
Upvotes: 0
Reputation: 1735
Put this in app-routing.module.ts
imports: [
RouterModule.forRoot(
routes,
{ enableTracing: true }
)
]
The application will log out route behavior so you can investigate the issue.
For me, I think the problem is around Strange Issue #1, it can be cause by router function. Actions of router.navigate
and router.navigateByUrl
weren't be all the same.
Upvotes: 1
Reputation: 6240
You should not use pathMatch: 'full'
everywhere, it does not play well (especially if you have nested routes). The docs give you examples of the most common usages. It is usually a good idea to redirect empty string routes to avoid other issues.
Something like this should work:
const routes: Routes = [
{
path: '',
pathMatch: 'full',
redirectTo: 'dashboard',
},
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [LoggedInGuard],
},
{
path: 'team-view',
component: TeamViewComponent,
canActivate: [LoggedInGuard],
},
{
path: 'settings',
component: SettingsComponent,
canActivate: [LoggedInGuard],
},
{
path: 'leaderboard',
component: LeaderboardComponent,
canActivate: [LoggedInGuard],
},
{
path: 'achievements',
component: AchievementsComponent,
canActivate: [LoggedInGuard],
},
{ path: 'register', component: RegisterComponent },
{ path: 'login', component: LoginComponent },
];
Upvotes: 0