'ngrx action is called without calling it in effect
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 })
);
Solution 1:[1]
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 })
);
Solution 2:[2]
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 }
);
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 | acandylevey |
| Solution 2 | Amer |
