1

im having a method to dispatch the action to query the account and select the account. I'm not sure if this is the best practice to select the data after dispatching.

this._store.dispatch(AccountsPageActions.loadAccountWithDetails({ accountId: this._accountId }));
this.account$ = this._actionsSubject.pipe(
  filter(action => action.type === AccountsApiActions.loadAccountWithDetailsSuccess.type),
  switchMap(() => this._store.select(getAccountDetailById(this._accountId)).pipe(
    tap(account => {
      this.account = account;
      this.accountId = this._accountId;
      this._reportsService.setAccount(account);
    })
  ))
);

Can someone tell me a better practice to do this or is this the way to go?

  • Just to check, the action `loadAccountWithDetails` loads the details and selector `getAccountDetailById` gets the data from store? And you want to make sure that AccountDetails within the component are updated afterwards, correct? – mat.hudak Nov 08 '21 at 08:48
  • Yes, exactly this is my use case. – MarcelSauter Nov 08 '21 at 09:38

2 Answers2

1

You don't need to listen to the action dispatch. If it's designed correctly, your action will update the state and the selector will be updated. This is enough

ngOnInit() {
  this._store.dispatch(AccountsPageActions.loadAccountWithDetails({ accountId: this._accountId }));

  // If you want to use the account$ with async pipe
  account$ = this._store.select(getAccountDetailById(this._accountId)).pipe(
    filter(account => !!filter), // ignore if no account is returned
    tap(account => {
      this.account = account;
      this.accountId = this._accountId;
      this._reportsService.setAccount(account);
    })
  ); // or .subscribe();
}

I would avoid listening to the action dispatches in the components, use effects for that.

mat.hudak
  • 2,803
  • 2
  • 24
  • 39
  • Thanks for your response, but why you would avoid to listen to the action? – MarcelSauter Nov 08 '21 at 12:20
  • 1
    Imagine that the `loadAccountWithDetails` action triggers an effect which then does some request to obtain data from API. It might take some time to finish and update the data in the store. But since you are listening to the action in the component, you'll trigger the selector before the data were updated. Of course, when state is updated so is your selector but if you manage to close the subscription before the actual update, you might be getting strange results. – mat.hudak Nov 08 '21 at 13:07
  • 1
    And it's also considered an anti-pattern solution. You should always listen to the store, via selectors, not the actions. Effects are meant to listen to the actions and act accordingly. – mat.hudak Nov 08 '21 at 13:08
  • Okay, makes sense. Thanks for your help! – MarcelSauter Nov 08 '21 at 14:27
0

I don't know why you need action subject, you can subscribe to actions using the code bellow and whenever there is a dispatch of that action it will trigger. keep action subscription in your constructor and then you can dispatch your action everywhere in your component

PLUCK is used to take the accountId value from the payload

import { Actions, ofType } from '@ngrx/effects';
import { map, pluck, switchMap, tap } from 'rxjs/operators';
...

constructor(private action: Actions) {
 const sub = this.action.pipe(
  ofType(AccountsApiActions.loadAccountWithDetailsSuccess.type),
  pluck('accountId'),
  switchMap((accountId) => this._store.select(getAccountDetailById(accountId)).pipe(
    tap(account => {
     this.account = account;
     this.accountId = this._accountId;
     this._reportsService.setAccount(account);
 }))).subscribe();
  
}

ngOnInit() {
  this._store.dispatch(AccountsPageActions.loadAccountWithDetails({ accountId: this._accountId }));
}
  
Fateh Mohamed
  • 20,445
  • 5
  • 43
  • 52
  • But with your solution, im dispatching nothing so i will never catch a action of my type or did i understand it wrong? – MarcelSauter Nov 08 '21 at 09:39
  • of course you have to call this._store.dispatch(AccountsPageActions.loadAccountWithDetails({ accountId: this._accountId })); in ngOnInit – Fateh Mohamed Nov 08 '21 at 09:40