Matt Brewerton
Matt Brewerton

Reputation: 886

Ngrx finalise effect by calling common action

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

Answers (1)

timdeschryver
timdeschryver

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

Related Questions