Подписаться срабатывает, когда данные не были изменены в магазине - PullRequest
0 голосов
/ 06 июня 2018

У меня есть приложение Angular 5 с ngrx.У меня есть массив объектов в магазине.Когда я подписываюсь на получение этого массива, событие изменения запускается, даже когда я не изменяю state.details.selectedOptions. Я изменил только state.details.page и был вызван подписчик.

Когда я меняю state.details.selectedOptions на обычное значение (строку), все работает, как и ожидалось.Как я вижу, проблема в массивах / вложенных элементах?

//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, потому что исходное состояние не былоне меняется.Я попытался использовать differentUntilChanged в select, но это не помогло

1 Ответ

0 голосов
/ 16 января 2019

Трудно понять наверняка, так как вы не добавили определение редуктора, но, как вы говорите, вы всегда устанавливаете selectedOptions в пустой массив, и я предполагаю, что вы имеете в виду в вашем редукторе действие по обновлению страницы, и когдаотправляется действие, вы изменяете его состояние следующим образом:

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

Redux использует неглубокую проверку на равенство, чтобы определить, изменилось ли состояние.Как говорит @Roomy, ["a"] === ["a"] возвращает false, поэтому Redux увидит вышеизложенное как изменение в state.selectedOptions при назначении новой ссылки.Использование DifferentUntilChanged () не имеет значения, поскольку он использует поверхностную проверку на равенство, поэтому, если вы передадите 2 массива с разными ссылками, это будет считаться изменением.

Если вам нужно только обновить страницу, обновите только свойство страницы и оставьте selectedOptions таким, как было:

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

Таким образом, наблюдатель в вашем компоненте не будет уведомлен оизменить в selectedOptions.

Вы также можете использовать

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

, потому что в этом случае selectedOptions все равно будет указывать на ту же ссылку.Это бессмысленно, но помогает объяснить суть.

...