Reputation: 886
I've got an application using NGRX as state management and I've got an effect which looks at the state to find an object by id, and calls the server if it fails. Both of these set the current object in the state, but I also have a loading indicator that I want the effect to handle - as if it has to call the server, there will be a delay.
I've setup my effect like this, which works:
fetchDealById$ = createEffect(() =>
this.actions$.pipe(
ofType(DealsApiActions.fetchDealById),
concatLatestFrom(() => this.store.select(selectDeals)),
switchMap(([action, deals]) => {
const dealFound = deals.find(x => x.id === action.id);
if (dealFound != undefined) return [
DealsApiActions.setCurrentDeal({ currentDeal: dealFound }),
DealsApiActions.setLoading({ loadingDeals: false })
];
return this.dealsService.fetchDealById(action.id).pipe(
switchMap((dealResponse: any) => [
DealsApiActions.setCurrentDeal({ currentDeal: dealResponse.data }),
DealsApiActions.setLoading({ loadingDeals: false })
])
)
}),
)
);
However I'm not happy with calling setLoading
twice. I tried adding finalize(() => DealsApiActions.setLoading({ loadingDeals: false })
(also with this.store.dispatch()
) but it doesn't seem to fire the action.
Is there a cleaner way I can deal with common actions at the end of an effect which may or may not have N delay?
Upvotes: 0
Views: 420
Reputation: 15497
You don't need two actions for this.
Instead, use DealsApiActions.setCurrentDeal
to also set loadingDeals
to false.
You can see an action as an event (loaded current deals), and the event can trigger multiple reducers/effects. I assume the loading indicator and the deal live in the same reducer, so you can set the deal, and also set the loading indicator in one go.
Upvotes: 1