I'm using Angular 7 along with NgRx. I have created a selector to get some data from the store using filter
, but this selector emits when anything on the store changes, even if it is not related to my selector.
I have created a demonstration of my issue. Here is my selector:
export const getMyArrayFilter = createSelector(
getCounterState,
state => state.myArray.filter(x => x === 'new Item')
);
And here I am using my getMyArrayFilter
selector:
this.store.pipe(select(fromRoot.getMyArrayFilter)).subscribe(x => console.log(x));
But as mentioned, this selector
will emit anytime anything changes on the state.
Please take a look at this StackBlitz demonstration.
If you try clicking on either the "Add item to array" or "-" or "+" buttons, then my getMyArrayFilter
will emit, and log to the console each time. Should't my selector only emit values IF the myArray
on my state changes?
I have taken a look at this SOF question which mentions using distinctUntilChanged
but that doesn't seem to work for me.
I'm using Angular 7 along with NgRx. I have created a selector to get some data from the store using filter
, but this selector emits when anything on the store changes, even if it is not related to my selector.
I have created a demonstration of my issue. Here is my selector:
export const getMyArrayFilter = createSelector(
getCounterState,
state => state.myArray.filter(x => x === 'new Item')
);
And here I am using my getMyArrayFilter
selector:
this.store.pipe(select(fromRoot.getMyArrayFilter)).subscribe(x => console.log(x));
But as mentioned, this selector
will emit anytime anything changes on the state.
Please take a look at this StackBlitz demonstration.
If you try clicking on either the "Add item to array" or "-" or "+" buttons, then my getMyArrayFilter
will emit, and log to the console each time. Should't my selector only emit values IF the myArray
on my state changes?
I have taken a look at this SOF question which mentions using distinctUntilChanged
but that doesn't seem to work for me.
- That is normal selector will emit new value when there is any change in the store. I dont understand what is your problem here – Tony Commented Jul 18, 2019 at 15:33
-
@TonyNgo shouldn't my selector only emit values if
myArray
changes on my state? – ViqMontana Commented Jul 18, 2019 at 15:37 -
Selector will emit value when there is any change. In your code you call 3 times to
fromRoot.getCount()
so it will return 3 times data – Tony Commented Jul 18, 2019 at 15:39
2 Answers
Reset to default 4As Alejandro pointed out, this is because there's a new reference for myArray
.
You can modify the memoization to your needs, Alex Okrushko does exactly this in his talk NgRx: Selectors are more powerful than you think
Doing some testing with your example I just notice that ngrx pare the arrays by reference and not by every item inside of it, what this means is that since the function filter return a new array with a new reference ngrx thinks that is different and that is why the subscribe is called every time something changes.
Creating a new copy will have the same effect:
export const getMyArrayFilter = createSelector(
getCounterState,
state => [ ...state.myArray ]
);