When I refresh the page in the system while logged in, the page always displays the login interface first and then switches back to the system page. During this period, the URL does not change.
package.json:
"dependencies": {
"@angular/animations": "^18.2.0",
"@angular/cdk": "^18.2.0",
"@angular/common": "^18.2.0",
"@angular/compiler": "^18.2.0",
"@angular/core": "^18.2.0",
"@angular/forms": "^18.2.0",
"@angular/platform-browser": "^18.2.0",
"@angular/platform-browser-dynamic": "^18.2.0",
"@angular/platform-server": "^18.2.0",
"@angular/router": "^18.2.0",
"@angular/ssr": "^18.2.0",
"@ant-design/icons-angular": "^18.0.0",
"crypto-js": "^4.2.0",
"express": "^4.19.2",
"ng-zorro-antd": "^18.1.0",
"rxjs": "~7.8.1",
"tslib": "^2.6.3",
"zone.js": "~0.14.10"
},
"devDependencies": {
"@angular-devkit/build-angular": "^18.2.0",
"@angular/cli": "^18.2.0",
"@angular/compiler-cli": "^18.2.0",
"@types/crypto-js": "^4.2.2",
"@types/express": "^4.17.21",
"@types/jasmine": "~5.1.4",
"@types/lodash": "^4.17.7",
"@types/node": "^22.3.0",
"jasmine-core": "~5.2.0",
"karma": "~6.4.4",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.1",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.5.4"
}
Route-Guard Code:
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): boolean | Promise<boolean> {
const secretKey = this.storageService.getSessionItem('secretKey');
const encryptedUser = this.storageService.getItem('user');
const encryptedMenus = this.storageService.getItem('menus');
if (!secretKey || !encryptedUser || !encryptedMenus) {
this.message.error('登录凭证过期,请重新登录。');
setTimeout(() => {
this.router.navigate(['/login']); // If I delete this code, the problem will not occur
}, 0);
return false;
}
……
}
canActivateChild(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): boolean | Promise<boolean> {
return this.canActivate(route, state);
}
app.routes.ts
export const routes: Routes = [
{
path: '',
// canActivateChild: [AuthGuard],
children: [...loginRoutes],
},
{
path: 'dashboards',
canActivate: [AuthGuard],
children: [...dashboardRoutes],
},
{
path: 'planmanage',
canActivateChild: [AuthGuard],
children: [...planManageRoutes],
},
{
path: '**',
redirectTo: '/dashboards',
},
app.component.html
<!-- System internal page -->
<ng-container *ngIf="!isLoginRoute">
……
<div class="inner-content">
<router-outlet></router-outlet>
</div>
……
</ng-container>
<!-- login page -->
<router-outlet *ngIf="isLoginRoute"></router-outlet>
app.compnent.ts
constructor(
private router: Router,
private cdr: ChangeDetectorRef,
) {
this.router.events.subscribe((event) => {
if (event instanceof NavigationEnd) {
this.isLoginRoute = this.router.url === '/login';
this.cdr.detectChanges();
}
});
}
What I want to achieve is that when a logged-in user is on the system's internal page, the refresh is still within the system, instead of displaying the login interface and then switching back to the system. I have tried to make routing decisions in app.component.ts, as well as in the login and dashboard pages, but none of them can prevent the problem from happening.
You can return the router.createUrlTree
instead of false
, this will work fine, the setTimeout is incorrect, we should return the navigation and not fire it as a sideeffect inside the canActivate.
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): boolean | Promise<boolean> {
const secretKey = this.storageService.getSessionItem('secretKey');
const encryptedUser = this.storageService.getItem('user');
const encryptedMenus = this.storageService.getItem('menus');
if (!secretKey || !encryptedUser || !encryptedMenus) {
this.message.error('登录凭证过期,请重新登录。');
return this.router.createUrlTree(['/login']);;
}
……
}
If you have SSR enabled in your application, then you need to wrap the HTML of your login.component.html inside a @defer
block so that it does not render in the server.
@defer() {
<!-- Login Page HTML goes here! -->
}