I'm making an Angular 2 app with @ngrx/store and @ngrx/effects.
I'm struggling with understanding where to put logic outside of actions/effects etc and where to call service functions.
For example, with authentication...
AUTH_REQUEST
action with the login credentials as the payload.AUTH_SUCCESS
action with the token, username etc in the response object as a payload which goes to the reducer to update the AuthState
. eg: In AuthEffects
@Effect() authenticate$ = this.updates$
.whenAction(AuthActions.AUTHENTICATE_REQUEST)
.switchMap(update => this.api.post('/authenticate', update.action.payload)
.map((res:any) => ({type: AuthActions.AUTHENTICATE_SUCCESS, payload: res.json()}))
.catch((err:any) => Observable.of({ type: AuthActions.AUTHENTICATE_ERROR, payload: err }))
);
In AuthReducer
case AuthActions.AUTHENTICATE_SUCCESS:
return Object.assign({}, state, <AuthState>{
processing: false,
failed: false,
isLoggedIn: true,
token: action.payload.token,
username: action.payload.username,
accountId: action.payload.accountId,
});
What I want to know is:
AUTH_SUCCESS
action is processed. Do I do this from within the effects Reactive chain or....??AuthService
that needs to store the credentials (token etc) in LocalStorage. Where should I call this to "store the token" ie authService.store(userCredentials)
. Any help appreciated.
You need to run this command npm install @ngrx/effects — save to install required dependencies. You have to define the actual services to make the API calls. Finally, you need to register all the effects with the EffectsModules and import this module into your main module or feature module.
Where Does NgRx Store Data? NgRx stores the application state in an RxJS observable inside an Angular service called Store. At the same time, this service implements the Observable interface. So, when you subscribe to the store, the service actually forwards the subscription to the underlying observable.
} @ngrx/effects provides an Angular actions$ service (which is also an Observable ) to emit every action that has been dispatched by your application in a single stream. Its ofType() method can be used to filter the one or more actions we're interesting in before adding a side-effect.
Clearly, this isn't a definitive answer; it's just what I chose to do.
The CodeSequence/ngrx-store-router implements actions for the v3 router. However, it doesn't implement a action creator - just the string
types. I used a simple action creator so that I don't have to have to have action literals all over the place:
import * as ngrxStoreRouter from "ngrx-store-router";
@Injectable()
export class RouterActions {
static NAVIGATE: string = ngrxStoreRouter.RouterActions.navigating;
navigate(url: string): Action {
return {
payload: { url },
type: RouterActions.NAVIGATE
};
}
}
And I used an effects class to dispatch the router actions:
@Injectable()
export class RouterEffects {
...
@Effect()
createUser(): Observable<Action> {
return this.stateUpdates_
.whenAction(AuthActions.CREATE_USER_SUCCESS)
.map((update) => update.action.payload)
.switchMap((payload) => {
return Observable.of(this.routerActions_.navigate("/on-board"));
});
}
...
}
My reasoning was this doesn't involve the authentication effects knowing anything about routing, it makes it easy to write tests for router effects, and the router actions fit in nicely with the @ngrx/store-devtools.
Regarding your second question, I'd be inclined to wire it up to a ..._SUCCESS
action in an effect.
I'd be interested in hearing about alternative approaches.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With