I am encountering an infinite loop issue when this component is loading. Does anyone have any suggestions on how to resolve this?
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Select, Store } from '@ngxs/store';
import { Observable } from 'rxjs';
import { UserProfile } from 'src/app/core/interfaces/userProfile';
import { GetUser } from './state/profile.action';
import { ProfileState } from './state/profile.state';
@Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
@Select(ProfileState.userProfile) userProfile$!: Observable<UserProfile>;
userId! :number;
constructor(private store:Store,private router:Router) {}
ngOnInit() {
this.userProfile$.subscribe(userProfileData => {
this.userId = userProfileData.id
this.store.dispatch(new GetUser(this.userId));
this.router.navigate(['/profile']);
});
}
}
This is the service
import { Injectable } from '@angular/core';
import { HttpClient, } from '@angular/common/http';
import { UserProfile } from 'src/app/core/interfaces/userProfile';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class UserService {
constructor(private httpClient: HttpClient) { }
private USER_PROFILE = 'http://localhost:8080/api/user/userProfile/';
getUser(id:number):Observable<UserProfile>{
return this.httpClient.get<UserProfile>(this.USER_PROFILE + id);
}
}
And the state code
import {Action, Selector, State, StateContext} from '@ngxs/store';
import { Login, Logout} from './auth.action';
import { LoginService } from '../login.service';
import { tap } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { Roles } from 'src/app/core/interfaces/role';
import { User } from 'src/app/core/interfaces/user';
export class AuthStateModel {
accessToken: string | undefined;
loggedInUser: User|undefined;
username: string | undefined;
email:string|undefined;
roles:string |undefined;
id: number |undefined;
}
@State<AuthStateModel>({
name: 'auth',
defaults: {
loggedInUser:undefined,
accessToken: undefined,
username: undefined,
email:undefined,
roles:undefined,
id: undefined
}
})
@Injectable()
export class AuthState {
result: null;
@Selector()
static isAuthenticated(state: AuthStateModel): boolean {
return !!state.accessToken;
}
@Selector()
static loggedInUser(state: AuthStateModel) {
return state.loggedInUser;
}
@Selector()
static role(state: AuthStateModel) {
return state.roles;
}
@Selector()
static getToken(state: AuthStateModel) {
return state.accessToken;
}
@Selector()
static loggedInUserName(state: AuthStateModel) {
return state.username;
}
constructor(private loginService: LoginService) {}
@Action(Login)
login(ctx: StateContext<AuthStateModel>, action: Login) {
return this.loginService.login(action.payload.username, action.payload.password).pipe(
tap((result: { accessToken: string, username:string,email:string,roles:Roles,loggedInUser:string,id:number, password:string, name:string, token:string}) => {
ctx.patchState({loggedInUser:result});
window.localStorage.setItem('token',result.accessToken)
window.localStorage.setItem('username',result.username)
window.localStorage.setItem('email',result.email)
window.localStorage.setItem('roles',result.roles)
window.localStorage.setItem('id',result.id.toString())
})
);
}
@Action(Logout)
logout(ctx: StateContext<AuthStateModel>) {
this.loginService.logout()
const state = ctx.getState();
ctx.setState({...state,
loggedInUser:undefined,
accessToken: undefined,
username: undefined,
email:undefined,
roles:undefined,
});
return state;
};
}
**And the other State **
import { Injectable } from "@angular/core";
import { Action, Selector, State, StateContext } from "@ngxs/store";
import { tap } from "rxjs/operators";
import { UserProfile } from "src/app/core/interfaces/userProfile";
import { UserService } from "../user.service";
import { GetUser } from "./profile.action";
export class ProfileStateModel {
userProfile: UserProfile|undefined;
}
@State<ProfileStateModel>({
name: 'profile',
defaults: {
userProfile:undefined,
}
})
@Injectable()
export class ProfileState {
profile!: UserProfile;
@Selector()
static userProfile(state: ProfileStateModel) {
return state.userProfile;
}
constructor(private userService: UserService) {}
@Action(GetUser)
getUser(ctx: StateContext<ProfileStateModel>, action: GetUser ){
const state = ctx.getState();
return this.userService.getUser(action.payload).pipe(
tap((result) => {
ctx.setState({
...state,
userProfile:result
});
})
);
}
}
Ok so im trying to take the ID from auth.state that is arledy dispatched.. and pass id as argument to make a http call and get the userProfile data, but i get stack in infinity loop.... i dont know if this is a corect way to do it or it is good practise as code... but this is the way that i thought that could be the best for my api and front end project.... any idea??