Chris Edgington
Chris Edgington

Reputation: 3246

Angular shared service not updating values

I have an Angular app with an auth service where i'm handling the user state like so -

@Injectable()
export class AuthService extends HttpService<User> {

    private readonly _user: BehaviorSubject<User>;

    public user$: Observable<User>;

    constructor(http: HttpClient) {
    super(http, 'users');
    this._user = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('user')));
    this.user$ = this._user.asObservable();
    }

    signIn(email: string, password: string): Observable<User> {
    return this.http.post<User>(this.path + '/login', { email: email, password: password})
        .pipe(map(user => {
        if (user && user.token) {
            localStorage.setItem('token', user.token);
            localStorage.setItem('user', JSON.stringify(user));
            this._user.next(user);
        }
        return user;
        }));
    }
}

Now this in my sign in component this works fine and the user is successfully returned -

export class SignInComponent {

    constructor(private auth: AuthService, private router: Router) { }

    signIn(email: string, password: string): void {
    this.auth.signIn(email, password).subscribe(user => {
        this.loading = false;
        this.router.navigate(['/pages/dashboard']);
    }, error => {
        this.failed = true;
        this.loading = false;
    });
    }
}

However in the component I'm redirected to after the sign in the user observable is null -

export class DashboardComponent implements OnInit {

    constructor(
        private authService: AuthService,
    ) { }

    ngOnInit() {

        this.authService.user$.subscribe(user => {
            console.log(user); // <- the user here is null!
        })
    }
}

If I refresh the browser the user object is successfully returned.

I assumed you could share data this way between components but it appears this isn't the case. How would I achieve this?

I should also say the sign in and dashboard components are in different modules.

Upvotes: 1

Views: 280

Answers (1)

mbojko
mbojko

Reputation: 14679

However in the component I'm redirected to after the sign in the user observable is null

probably because its ngOnInit runs after user$ emitted. You need a ReplaySubject, not a BehaviorSubject.

BTW, you can replace your map

.pipe(map(user => {
    if (user && user.token) {
        //...

with tap, will make the return statement unnecessary.

Upvotes: 1

Related Questions