MaliTica
MaliTica

Reputation: 70

Angular displays logged user on load even though localstorage is empty

So I am currently following some course. I have simple login form inside the nav bar

<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-primary">
    <div class="container">       
            <a class="navbar-brand" routerLink='/' routerLinkActive='active' >Dating app</a>

            <ul class="navbar-nav mr-auto" >
                <ng-container *ngIf="accountService.currentUser$ | async">
                    <li class="nav-item">
                        <a class="nav-link" routerLink="/members" routerLinkActive='active'>Matches</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" routerLink="/lists" routerLinkActive='active'>Lists</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" routerLink="/messages" routerLinkActive='active'>Messages</a>
                    </li>
                </ng-container>
           
            </ul>

         

            <div class="dropdown" *ngIf="(accountService.currentUser$ | async) as user" dropdown>
                <a class="dropdown-toggle text-light" dropdownToggle>Welcome {{user.username | titlecase}}</a>
                <div class="dropdown-menu mt-3" *bsDropdownMenu>
                    <a class="dropdown-item">Edit profile</a>
                    <div class="dropdown-divider"></div>
                    <a class="dropdown-item" (click)="logout()">Logout</a>
                </div>
            </div>

            <form *ngIf="(accountService.currentUser$ | async) === null" #loginForm="ngForm" class="form-inline mt-2 mt-md-0" (ngSubmit)="login()" 
            autocomplete="off">
            <input 
                name="username"
                [(ngModel)]="model.username"
                class="form-control mr-sm-2" 
                type="text" 
                placeholder="Username">
            <input 
                name="password"
                [(ngModel)]="model.password"
                class="form-control mr-sm-2" 
                type="password" 
                placeholder="Password">
            <button class="btn btn-success my-2 my-sm-0" type="submit">Login</button>
        </form>

           
        </div>

</nav>

I want to show Welcome {username} when the client is logged in, and login form when nobody is logged in. The thing is when I start the angular app, it is displaying this

enter image description here

instead of this:

enter image description here

Localstorage is empty when I start the app so I literaly have no idea why is this happening. The service I am using looks like this:

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ReplaySubject } from 'rxjs';
import { map } from 'rxjs/operators'
import { User } from '../_models/User';



@Injectable({
  providedIn: 'root'
})
export class AccountService {
  baseUrl = "https://localhost:5001/api/";
  private currentUserSource = new ReplaySubject<User>(1);
  currentUser$ = this.currentUserSource.asObservable();
  constructor(private http: HttpClient) { }

  login(model:User)
  {
    return this.http.post<User>(this.baseUrl + 'account/login',model).pipe(
      map((response: User) => {
        const user = response;
        if(user)
        {
          localStorage.setItem('user',JSON.stringify(user));
          this.currentUserSource.next(user);
        }
      })
    )
  }

  register(model:User)
  {
    return this.http.post<User>(this.baseUrl+'account/register',model).pipe(
      map((user: User) => {
        if(user)
        {
          localStorage.setItem('user',JSON.stringify(user));
          this.currentUserSource.next(user);
        }
      })
    )
  }

  setCurrentUser(user: User){
    this.currentUserSource.next(user);
  }


  logout()
  {
    localStorage.removeItem('user');
    this.currentUserSource.next(null!);
  }
}

The only difference I can spot between my code and the code in tutorial is

this.currentUserSource.next(null!);

and in tutorial it is

this.currentUserSource.next(null);

But when I use null without !, it gives me error and I could not fix it.

I know this might be something silly but I could not get around it

Upvotes: 1

Views: 531

Answers (2)

Shalom Peles
Shalom Peles

Reputation: 2632

In your component, you check if the current user is truthy:

<div class="dropdown" *ngIf="(accountService.currentUser$ | async) as user" dropdown>

The problem is that when the sessionStorage is empty, you put an empty object ({}) as the current user. And, since objects are always truthy, the welcome message appears:

// src/app/app.component.ts:27
const user: User = JSON.parse(localStorage.getItem('user') || '{}');
this.accountService.setCurrentUser(user);

In this case, you should set the current user to null:

// src/app/app.component.ts:27
const user: User | null = JSON.parse(localStorage.getItem('user') || null);

And in the service change the types to allow this:

private currentUserSource = new ReplaySubject<User|null>(1);
// ...
setCurrentUser(user: User | null){
// ...

Upvotes: 1

Try to change ReplaySubject for BehaviorSubject :

private currentUserSource = new BehaviorSubject<User|null>(null);

and

this.currentUserSource.next(null);

Upvotes: 1

Related Questions