I am trying to write an effect for an action but it is throwing an error as: “Effect “n.loadInfo$” dispatched an invalid action: null Error“
I have my effect as below:
@Effect() loadInfo$ = this.actions.ofType(fromHeaderActions.EInfoActions.OPEN_INFO).pipe( withLatestFrom( this.store.select(fromSelectors.GetINFOPayload)), switchMap(([action, infoPayLoad]) => { let cAction: fromHeaderActions.OpenINFOWIdget = <fromHeaderActions.OpenINFOWIdget>action; return this.infoService.loadINFO(infoPayLoad).pipe( // Dispatch success action map(response => new fromHeaderActions.OpenINFOWIdgetSuccess(response)), catchError(error => { return of(new fromHeaderActions.OpenINFOWIdgetFail(error.message)) }) ) }) );
I have my action defined as below:
export class OpenINFOWIdget extends BaseGetDetailsAction implements Action { readonly type = EInfoActions.OPEN_INFO; constructor() { super(); } } //added action after the comment export class OpenINFOWIdgetSuccess extends BaseGetDetailsAction implements Action { readonly type = EInfoHeaderActions.OPEN_INFO_SUCCESS; constructor(public payload: INFO) { super(); } } export class OpenINFOWIdget extends BaseGetDetailsAction implements Action { readonly type = EInfoActions.OPEN_INFO_FAIL; constructor(public payload: string) { super(); } }
And in the service as below:
public INFOPayloadsource = new BehaviorSubject<INFO>(initINFO); infoPayload$ = this.INFOPayloadsource.asObservable(); private SelectedInfoSource = new Subject<INFO>(); selectedInfo$ = this.SelectedInfoSource.asObservable(); loadINFO(payload: INFO): Observable<INFO> { if (payload != null) { this.IsInfoEnableSource.next(true); this.InfoPayloadsource.next(payload); } return this.selectedInfo$; }
I have selector as below that is used in the effect:
export const GetINFOPayload = createSelector(getInfoState, (state: InfoDetailsState) => { if (state) { if (state.infoDetails != null && state.infoDetails.INFODetail != null && state.infoDetails.INFODetail.Active != null) { let payload: INFO = { ...initINFO }; payload = state.infoDetails.INFODetail.Active; return payload; } } return null; });
Create reducer as below after the comment:
case fromInfoDetailsHeaderActions.EInfoHeaderActions.OPEN_INFO: { return { ...state, IsScreenOverlay: true, IsEditable: false } }; case fromInfoDetailsHeaderActions.EInfoHeaderActions.OPEN_INFO_SUCCESS: { return { ...state, IsScreenOverlay: false, IsEditable: true } };
I would really appreciate if anyone can help on it. Thank you!
Advertisement
Answer
Your effect is trying to dispatch the result of this.infoService.loadINFO()
, which is why you get the error saying that it is not a valid action.
You should map
this to a success action instead:
@Effect() loadInfo$ = this.actions.ofType(fromHeaderActions.EInfoActions.OPEN_INFO).pipe( withLatestFrom( this.store.select(fromSelectors.GetINFOPayload) ), switchMap(([action, infoPayLoad]) => { let cAction: fromHeaderActions.OpenINFOWIdget = <fromHeaderActions.OpenINFOWIdget>action; return this.infoService.loadINFO(infoPayLoad).pipe( // Dispatch success action map(response => new fromHeaderActions.OpenINFOWIdgetSuccess(response)), catchError(error => { return of(new fromHeaderActions.OpenINFOWIdgetFail(error.message)) }) ) }) );
You will also need to add the corresponding action and handle it in your reducer, if necessary.