'How to dispatch api response data into ngrx store from a ngrx effect service
I'm struggling to dispatch data to the ngrx store after data is fetched from Api. I actually have a ngrx effect service loginEffect.ts as bellow :
constructor(private actions$: Actions, private authService: AuthService, private router: Router, private store: Store){}
login$ = createEffect(() => this.actions$.pipe(
ofType(loginAction),
switchMap(({request}) => {
return this.authService.login(request).pipe(
map((currentUser: CurrrentUserInterface) => {
return loginSuccessAction({currentUser})
}),
tap(() => (request.user.username == 'admin') ? this.router.navigate(['dashboard']) : this.router.navigate(['login']) ),
catchError(() => {
return of(loginFailureAction())
})
)
})
))
It calls the loginService.ts that perfom the api call and login operation like bellow:
export class loginService {
constructor(private http: HttpClient, private store: Store){}
login(data: LoginRequestInterface): Observable<CurrrentUserInterface>{
const url = environment.apiUrl + '/users/login'
const Option ={ headers: new HttpHeaders({
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
'USER_CODE': data.user.USER_CODE})
};
return this.http
.post<authResponseInterface>(url, { username: data.user.username, password: data.user.password }, Option)
.pipe(map((response: authResponseInterface) => response.user))
}
}
The login is successfull and user is redirected well. But I need to grab the token, userId and user_code from the response yielded by the api, and then dispatch them into the ngrx store in order to use them as params for other api call. But I'm hitting the wall of dispatching such data to the ngrx store. I was good at redux with React app, but not with ngrx. So How can I dispatch the response to ngrx store from the loginEffect.ts or from the loginService.ts? I thought that dispatching it inside the loginEffect.ts is a better bet and so I called the
this.store.dispatch(loginSuccessAction({currentUser}))
this but it caused visual studio editor to error out as shown on screenshot:

In the loginAction.ts I have loginSuccessAction like this:
export const loginSuccessAction = createAction(
actionTypes.LOGIN_SUCCES,
props<{currentUser: CurrrentUserInterface}>()
)
I even think to write an action to excecute on(loginSuccessAction, ...) in the reducer.ts, but I can't do that because the values that I have to dispatch are only available in the loginEffect.ts or from the loginService.ts. I will be very greatfull for your hepl. Thanks in advance.
EDITED ACCORDING TO @MikeOne's CONTRIBUTION
When trying to reduce the payload to reducers.ts I did this:
on(loginSuccessAction,
(state: AuthStateInterface): AuthStateInterface => ({
...state,
USER_CODE:'admin',
token: 'xrdxgfchgb',
userId : 63,
}))
And redux devtool displays the exact data I reduced in there, but those data aren't real data from api, as you can see they are manually set. So my struggle is about how to set the currentUser data fetched from the api response in the reducer. This is the loginSuccessAction that implements the currentUser interface:
export const loginSuccessAction = createAction(
actionTypes.LOGIN_SUCCES,
props<{currentUser: CurrrentUserInterface}>()
)
And this is how logingEffect was supposed to map the api response to currentUser:
@Injectable()
export class loginEffect {
constructor(private actions$: Actions, private authService: AuthService, private router: Router, private store: Store){}
login$ = createEffect(() => this.actions$.pipe(
ofType(loginAction),
switchMap(({request}) => {
console.log(request); return this.authService.login(request).pipe(
map((currentUser: CurrrentUserInterface) => {
console.log(currentUser); return loginSuccessAction({currentUser})
}),
tap(() => (request.user.username == 'admin') ? this.router.navigate(['dashboard']) : this.router.navigate(['login']) ),
catchError(() => {
return of(loginFailureAction())
})
)
})
))
}
As you can see, I console.log the currentUser in the
map((currentUser: CurrrentUserInterface) => {
console.log(currentUser); return loginSuccessAction({currentUser})
})
But it gives undefined in console. Is my "request" properly mapped to currentUser inside the loginEffect.ts ? If so how can I then pass it in reducer.ts . Thank you so much.
Solution 1:[1]
Your reducer should use the prop from your action i.e currentUser like below
on(loginSuccessAction,
(state: AuthStateInterface, {currentUser}): AuthStateInterface => ({
...state,
USER_CODE:currentUser.user.username,
token: <token>,
userId : <id>,
}))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | mak15 |
