4
votes

I've started using ngrx/store and combining it with angular/router. So far so good, except that I can’t get selecting from store working inside the canActivate method of my guard. When selecting and subscribing from the store inside a component, everything works, however when trying to retrieve a value inside the canActivate function it keeps returning undefined.

From my understanding, and it sounds logical, the canActivate method is running before the store is initialized (because it’s returning undefined, and not the initial state). I have been reading a lot but didn’t found a decent answer explaining this behaviour.

Firebase Auth + Routing + Ngrx

My usecase is that I have setup authentication using Firebase Auth + Ngrx + Router. The flow goes as following:

  • Enter credentials in form.
  • Click submit, this will dispatch a LOGIN action.
  • An ngrx/effect will be triggered, trying to login using firebase/auth: return LOGIN_SUCCESS or LOGIN_FAILED.
  • When LOGIN_SUCCESS, a parameter “loggedIn” is set to True in the sure and the user is redirected to the homepage (/home).
  • A guard (canActivate) is implemented on the (/home) endpoint which checks if the user is signed in using the store attribute (loggedIn).
  • Expecting false or true, but the store simply returns “undefined” in the select call. (However it does work properly inside a component by subscribing).

Also what I see in the Redux developer tools is that the route gets cancelled before the LOGIN_SUCCESS completes; this is another issue. However still I expect to retrieve false and not undefined.

Can someone explain me why this is happing?

At the moment I see two hacks, but I don’t like them.

  • Dispatch an action to make sure the store is initialized.
  • Use firebase.auth observable and bypass store.

Thank you for reading and understanding.

1
i can help if you can show your codebrijmcq

1 Answers

1
votes

did you check you initial state for your store ? Something like that :

export const initialUserState: UserState = {
  user: null
};

export interface UserState {
  user: Userbean;
}

And when you check your store, you could insure that you passed store init with a filter on your select, like this maybe :

store.pipe(
      select(getUser),
      filter(user=> !!user && user.loggedIn !== null)
    );

This article is quite nice about the way to implement login actions : https://mherman.org/blog/authentication-in-angular-with-ngrx/

And here this is the way to handle Observable and route redirect in the canActivate method : Returning an Observable<boolean> from canActivate method and redirect on false

Hope that could help :)