4

I would like to know if it's possible to filter store.select subscription by actions (like we do in Effects). See the code below:

this.store
  .select(mySelector)
  .subscribe(obj => { . //FILTER SUBSCRIPTION BY ACTION 
    this.object = obj; 
  });

Everytime when an action is dispatched (does not matter which action) every single active component(not destroyed and not unsubscribed) which has store.select.subscribe will be called.

If our application has 100 actions, everytime that 1 action is fired, all active components (not destroyed or unsubscribed) store.select.subscribe will be called. (If the state that affects component has not changed I know that we don't gonna have any problems as the state stills the same).

Why I ask this question?

Sometimes I need to execute some action in my component every time when the state which affects it changes. So, every time I need to do an if statement to check if the object has changed. If I have a filter for action, this if statement would not be necessary anymore, as I filtered the subscription for specific actions which affects my component. See the code that shows this if statement bellow:

myObject: any; //global object of my component


  constructor(
    private store: Store<AppState>,
  ) {
    this.store
      .select(mySelector)
      .subscribe(obj => {
        if(obj.id !== myObject.id) //changed{
          this.myObject = obj;
          doSomeActionInMyComponent()
        } else {
          this.myObject = obj;
        }
      });
  }

  doSomeActionInMyComponent() {
      //do some action using this.myObject
  }

It makes sense my thought or I misunderstood ngrx concepts? Should I use something else like effects for that?

Thanks in advance.

Lucas Santos
  • 2,991
  • 3
  • 19
  • 29

2 Answers2

2

This isn't possible, a selector reacts to a state change.

I do find it a bit strange that every selector is emitting a new result when you dispatch an action tho. Only the selectors affected by the state change should emit a new result, this is because internally a selector is caching the input and if the input does not change it won't execute.

From the docs:

When using the createSelector and createFeatureSelector functions @ngrx/store keeps track of the latest arguments in which your selector function was invoked. Because selectors are pure functions, the last result can be returned when the arguments match without reinvoking your selector function. This can provide performance benefits, particularly with selectors that perform expensive computation. This practice is known as memoization.

If you got a reproduction I'm happy to take a look.

timdeschryver
  • 14,415
  • 1
  • 19
  • 32
0

You may instead subscribe the Action, but that won't be a good practice anyway.

constructor(action$: Actions) {
        action$.pipe(
           ofType(YourAction.ANY_ACTION),
           takeUntil(this.destroyed$)
        )
        .subscribe(() => {
          ...
        });
}
Vincent
  • 1,178
  • 1
  • 12
  • 25