Reputation: 91
I have made a effect to load data and actions to load, load success and load failure. Effect is working but it calls both actions(success, failure) but I returned just load success. If I move failure reducer above success it calls first failure and then success and similary if i switch them. I didn`t dispatch any of them somewhere else. What am I doing wrong?
loadFilteredElements$ = createEffect(() =>
this.actions$.pipe(
ofType(loadFilteredElements),
switchMap((action) => this.elementsService.getFilteredElementsForProject(action.filter)),
map((data) => loadFilteredElementsSuccess(data.values!))
)
);
on(ElementActions.loadFilteredElementsSuccess, (state: ElementState, { elements }) =>{
console.log('succes action');
return ({
...state,
elements: elements,
error: undefined,
status: StatusEnum.success,
})}),
on(ElementActions.loadFilteredElementsFailure, (state: ElementState, { error }) =>{
console.log('failure');
return ({
...state,
status: StatusEnum.error,
error: error,
})}),
on(ElementActions.changeElementFilter, (state: ElementState, { filter }) =>{
console.log('changefilter');
return ({
...state,
filter: filter,
})})
export const loadFilteredElements = createAction('[Element[]] load elements from server', (filter: ElementFilter) => ({
filter,
}));
export const loadFilteredElementsSuccess = createAction(
'[Elements[] API] elements succesfully loaded',
(elements: AppElement[]) => ({ elements })
);
export const loadFilteredElementsFailure = createAction(
'[Elements[] API] elements succesfully loaded',
(error: ResponseResultEnum) => ({ error })
);
Upvotes: 0
Views: 1810
Reputation: 326
Looks like your failure action is using the same type as your success action, so infact you have declared the same action twice.
Change
export const loadFilteredElementsSuccess = createAction(
'[Elements[] API] elements succesfully loaded',
(elements: AppElement[]) => ({ elements })
);
export const loadFilteredElementsFailure = createAction(
'[Elements[] API] elements succesfully loaded',
(error: ResponseResultEnum) => ({ error })
);
to
export const loadFilteredElementsSuccess = createAction(
'[Elements[] API] elements succesfully loaded',
(elements: AppElement[]) => ({ elements })
);
export const loadFilteredElementsFailure = createAction(
'[Elements[] API] elements failed to load',
(error: ResponseResultEnum) => ({ error })
);
Upvotes: 2
Reputation: 6706
The NgRx Effect
dispatches an action by default, if you didn't change that.
So, any action returned from the effect stream (using map
operator) is then dispatched back to the Store
.
As described in @ngrx/effects docs:
Metadata is attached to the observable streams using the createEffect function. The metadata is used to register the streams that are subscribed to the store. Any action returned from the effect stream is then dispatched back to the Store.
To change this behavior, add { dispatch: false }
to the createEffect
function as the second argument, like the following:
loadFilteredElements$ = createEffect(
() =>
this.actions$.pipe(
ofType(loadFilteredElements),
switchMap((action) => this.elementsService.getFilteredElementsForProject(action.filter)),
map((data) => loadFilteredElementsSuccess(data.values!))
),
{ dispatch: false }
);
Upvotes: 0