Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular data loss on reload using BehaviorSubject

I'm using a data service to send the user data to the app and display the username in my header component. If I sign in in my app with login component the username is correctly displayed, but when I reload the page the user data disappears.

on login Before reload

enter image description here enter image description here

after reload

enter image description here enter image description here

the user data comes from a data service that use a BehaviorSubject:

data.service.ts

    export class DataService {
    
      private userSource = new BehaviorSubject({});
      currentUser = this.userSource.asObservable().pipe(distinctUntilChanged());
    
      constructor(private injector: Injector, private api: UtentiApiService) { }
    
      getUser() {
        return this.currentUser;
      }
    
      getUserFromToken() {
        const authService = this.injector.get(AuthService);
        const token = authService.getToken();
        const userIdToken = jwt_decode(token);
        // console.log(userIdToken);
        return this.api.getUtente(userIdToken.userId);
      }
    
      getPermissionsFromToken(): Observable<any> {
        const authService = this.injector.get(AuthService);
        const token = authService.getToken();
        const userIdToken = jwt_decode(token);
    
        return of(userIdToken.permArr);
      }
      changeUser(user: object) {
        this.userSource.next(user);
      }
    
    }

in header component I consume the service:

header.component.ts

    export class HeaderComponent implements OnInit {
      user: object;
    
      constructor(private router: Router, private authService: AuthService, private data: DataService) { }
    
    
      ngOnInit() {
        this.getUser();
      }
    
      getUser() {
        this.data.getUser().subscribe(utente => {
          this.user = utente;
          console.log(this.user);
        });
      }
    
      onLogout() {
        this.authService.logoutUser();
      }
    
      sendUser(user) {
        this.data.changeUser(user);
      }
    }

in the login component I send the user data to the data service, but on reload the login component is not fired, so I have no user data in the service nor in the header. How can I fix this bug?

Here a stackblitz with the full code: https://stackblitz.com/github/ufollettu/SEANSA

Thank you for help

like image 546
ufollettu Avatar asked Aug 08 '18 09:08

ufollettu


2 Answers

From your code:

private userSource = new BehaviorSubject({});
  currentUser = this.userSource.asObservable().pipe(distinctUntilChanged());

  constructor(private injector: Injector, private api: UtentiApiService) { }

  getUser() {
    return this.currentUser;
  }

Your userSource is a BehaviorSubject which contains nothing when you start your application (also on reload).

When you login a user you call:

changeUser(user: object) {
    this.userSource.next(user);
  }

After this call your BehavoirSubject contains a user. But you only do this during login process.

When you reload your page you need to fetch the access token from localstorage, and call next on the BehavoirSubject with the current user.

You can do that in the constructor of the dataService for instance.

like image 125
J. S. Avatar answered Nov 06 '22 15:11

J. S.


Use SessionStorage or localStorage or cookies to store your data.

When you hit refresh copy your data in any of the above storage and on init copy it back into your variable. Check below example. Replace the sessionStorage to localStorage to store data in localStorage.

In AppComponent

    ngOnInit() {
    if (sessionStorage.getItem("user")) {
      this.data.changeUser(sessionStorage.getItem("user"));
    }
      }
@HostListener('window:beforeunload', ['$event'])
      unloadNotification($event: any) {
        sessionStorage.setItem("user", this.getUser());
      }
like image 24
Krishna Avatar answered Nov 06 '22 15:11

Krishna