Search code examples
angularstatestate-managementngxs

NGXS dispatch-decorator plugin not working with withLatestFromOperator


Im using NGXS as my state management along with its plugin https://github.com/ngxs-labs/dispatch-decorator

I have the following code on my component:

this.route.paramMap.pipe(
  tap((params: ParamMap) => {
    this.facade.initializeForm();
  }),
  switchMap((params: ParamMap) => {
    const id = +params.get('id');
    return of(this.facade.viewOrder(id));
  }),
  withLatestFrom(this.facade.currentlyViewedDelivery$),

).subscribe((delivery) => {
  console.log('DELIVERY', delivery);
});

this is my the viewOrder():

  @Dispatch() viewOrder = (id: number) => new OrderAction.View(id);

However, the results on my subscribe tells me that currentlyViewedDelivery$ returns a value of null. When I tried delay() operator before withLatestFrom() it works. It gives me idea that the dispatch action is not finished yet. However, when I tried a normal dispatching using Store it works without using delay(). What might be the problem?

Thanks!


Solution

  • I'm not sure what you're trying to achieve, but the @Dispatch decorator shouldn't be used like that.

    What does this plugin do? Basically it overrides your method, take its return value (it has to be a single action, Observable or Promise), unwraps it (subscribes or resolves a Promise) and invokes dispatch under the hood for you.

    I assume that the View action handler does some asynchronous job, that's why you see the updated state value when you pipe with the delay operator.

    Frankly speaking you have to listen to the View action completion, see the below code:

    this.route.paramMap
      .pipe(
        tap((params: ParamMap) => {
          this.facade.initializeForm();
        }),
        switchMap((params: ParamMap) => {
          const id = +params.get('id');
          this.facade.viewOrder(id);
          return this.actions$.pipe(ofActionSuccessful(OrderAction.View), take(1));
        }),
        withLatestFrom(this.facade.currentlyViewedDelivery$)
      )
      .subscribe(delivery => {
        console.log('DELIVERY', delivery);
      });
    

    Where actions$ is an injected Actions class.

    If you prefer using facades then you can just move this logic to some facade method and call this method something else :)