Search code examples
angularngrx

angular 7 ngrx trigger subscription of all the fields when one field is updated


Hi I am using Ngrx as the state management for my frontend project. Recently I found all the subscriptions are triggered when one field in the state is updated.

Suppose I have a state with field A and B. Correspondingly, I have AComponent and BComponent subscribing the value of A and B. Now if I keep dispatching an action to update A. the subscription of B will also be triggered all the time even though the value of B is not updated.

At the moment, what I am doing is in the subscription function of B, I check whether or not the value is changed, such as

if (this.B !== B) {
    //do something
}

Is there any way that if I dispatch an action to update A, the subscription of B is not triggered? Or this is the a fundamental mechanism of NGRX?

Thank you

Update

Here is the selector I am using

this._store
  .select("appState")
  .pipe<T>(pluck("B"))
  .subscribe(callback);

Update 2

According to @Anarno's answer, I added the selector as follow

const BFeatureSelector = createFeatureSelector<string>('b');
export const BSelector = createSelector(
    BFeatureSelector,
    state => state
);

At the meanwhile, I print a message in reducer to make sure B is updated as

case app.ActionType.B: {
    console.info("b is update in reducter");
    return Object.assign({}, state, { b: action.payload });
}

And then I use this BSelector in BComponent in the following three methods

this._store.select(BSelector).subscribe(b=> {
  console.info("b is updated 1");
  console.info(b);
});

this._store
  .pipe(
    map(state => BSelector(state))
  )
  .subscribe(b=> {
    console.info("b is updated 2");
    console.info(b);
  });

this._store
  .pipe(select(notificationSelector))
  .subscribe(b=> {
    console.info("b is updated 3");
    console.info(b);
  });

What I observe is both b is updated 1 and b is updated 3 only printed once when the component is initialised while b is updated 2 is printed all the time when other fields in state is updated. However, none of console.info(b); in each method works. All three methods do not print the content of b.


Solution

  • You need a selector file, and make selectors like this:

    import { createFeatureSelector, createSelector } from '@ngrx/store';
    import { BState } from '../../../reducers/index';
    
    const selectBState = createFeatureSelector<BState>('BState');
    
    export const selectBvalue = createSelector(
      selectBState,
      state => state.value
    );