Reputation: 1
I have and Angular 5 app with ngrx. I have an array of objects in store. When I subscribe to get this array change event is fired even when I don't change state.details.selectedOptions. I changed only state.details.page and subscriber was called.
When I change state.details.selectedOptions to plain value (string) everything is working as expected. As I see the problem is in arrays/nested elements?
//store
const initialState = {
page: null,
selectedOptions: []
}
// selector
export const selectedOptionsSelector = createSelector(
(state: any) => state.details.selectedOptions
)
// also tried such variant
export const selectedOptionsSelector = (state: any) => state.details.selectedOptions
// Component
ngOnInit() {
this.store.select(selectedOptionsSelector).subscribe((res: any) => {
console.log('selectedOptions', res)
})
}
Update:
Basically in my case I always have empty array in selectedOptions because initial state didn't change. I tried using distinctUntilChanged in select but it didn't help
Upvotes: 0
Views: 1928
Reputation: 1226
It is hard to know for sure as you have not added your reducer definition, but as you say you always set selectedOptions to an empty array I will assume you mean in your reducer you have an action to update the page, and when the action is dispatched you modify its state as:
case Actions.Type.UPDATE_PAGE: {
return {
...state,
page: 'newValue',
selectedOptions: []
}
}
Redux uses shallow equality checking to determine if the state has changed. As @Roomy says, ["a"] === ["a"]returns false, therefore Redux will see the above as a change to state.selectedOptions as you are assigning a new reference. Using distinctUntilChanged() doesn't make a difference because it uses shallow equality checking, so if you pass 2 arrays with different references, it will consider this a change.
If you only need to update the page, update only the page property and leave selectedOptions as it was:
case Actions.Type.UPDATE_PAGE: {
return {
...state,
page: 'newValue'
}
}
This way the observer in your component won't be notified of a change in selectedOptions.
You could also use
case Actions.Type.UPDATE_PAGE: {
return {
...state,
page: 'newValue',
selectedOptions: state.selectedOptions
}
}
because in this case selectedOptions would still point to the same reference. This is pointless though, but it helps explaining the point.
Upvotes: 1