Angular 当存储区中的数据未更改时,正在触发订阅

Angular 当存储区中的数据未更改时,正在触发订阅,angular,ngrx,reselect,Angular,Ngrx,Reselect,我有和角5应用程序与ngrx。我有一个对象数组在存储中。当我订阅获取此数组时,即使我没有更改状态。详细信息。选择选项。我只更改了状态。详细信息。页面,并且调用了订阅者,也会触发更改事件 当我将state.details.selectedOptions更改为普通值(string)时,一切都正常工作。如我所见,问题出在数组/嵌套元素中 //store const initialState = { page: null, selectedOptions: [] } // selector ex

我有和角5应用程序与ngrx。我有一个对象数组在存储中。当我订阅获取此数组时,即使我没有更改状态。详细信息。选择选项。我只更改了状态。详细信息。页面,并且调用了订阅者,也会触发更改事件

当我将state.details.selectedOptions更改为普通值(string)时,一切都正常工作。如我所见,问题出在数组/嵌套元素中

//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)
  })
}
更新:


基本上在我的例子中,我总是在selectedOptions中有空数组,因为初始状态没有改变。我尝试在select中使用distinctUntilChanged,但没有帮助

很难确定,因为您没有添加reducer定义,但正如您所说,您总是将selectedOptions设置为空数组,我假设您的意思是,在reducer中,您有一个更新页面的操作,当该操作被调度时,您将其状态修改为:

case Actions.Type.UPDATE_PAGE: {
    return {
        ...state,
        page: 'newValue',
        selectedOptions: []
    }
}
Redux使用浅层相等性检查来确定状态是否已更改。正如@Roomy所说,[“a”]=[“a”]返回false,因此Redux会将上述内容视为对state.selectedOptions的更改,因为您正在分配一个新引用。 使用SuffTunTrimeDeD()并没有什么区别,因为它使用浅的相等性检查,所以如果您通过不同的引用传递2个数组,它会认为这是一个改变。p> 如果只需要更新页面,请仅更新页面属性,并保持选定选项不变:

case Actions.Type.UPDATE_PAGE: {
    return {
        ...state,
        page: 'newValue'
    }
}
这样,组件中的观察者将不会收到所选选项更改的通知

你也可以使用

case Actions.Type.UPDATE_PAGE: {
            return {
                ...state,
                page: 'newValue',
                selectedOptions: state.selectedOptions
            }
}

因为在这种情况下,selectedOptions仍然指向相同的引用。这是毫无意义的,但它有助于解释这一点。

您的描述很差,但可能是原语和实例的问题,您可能会注意到,
“abc”===“abc”
,但是
[“abc”!==[“abc”]
,所以基本上每次使用
{…}
[…]
时,您都在创建一个新实例,使用
rxjs
操作符,如
distinct
,在这里可能会非常有用,因为它允许比较新值和当前值,并且仅当它与使用自定义比较函数的前一个值不同时,才会发出新值