Как получить Observable, который излучает только тогда, когда значение свойства изменяется в массиве объектов в состоянии redux?

У меня есть состояние редукции в угловом приложении:

      export interface UIAction {
  name: string;
  isActive: boolean;
}


export interface IUIState {
  actions: UIAction[];
}

Я создал сервис angular, который подписывается на состояние и сохраняет объекты для каждого действия на карте и возвращает этот объект вызывающим абонентам, которые заинтересованы в значении isActive для определенного действия. Это примерно так:

      public getIsActive$(name: string): Observable<boolean> {  
  let sub = this.subsMap.get(name);
  return sub.asObservable();
}

Теперь я хочу изменить код и избавиться от карты со всеми объектами и сделать что-то вроде этого:

      public getIsActive$(name: string): Observable<boolean> {  
  return this.ngRedux.select<IUIState>('ui').pipe(
  /* this should use some operators so that
     the returned Observable emits only when 
     UIAction.isActive changes for the action 
     in question. The action in question is
     found from the state.actions-array using 
     parameter 'name' */
   )));
}

Как это сделать?

2 ответа

Надеюсь, я правильно понимаю это требование. Вы можете применить пользовательскую функцию к distinctUntilChanged() для более сложных случаев.

      public getIsActive$(name: string):Observable<boolean> {
  return this.ngRedux.select<IUIState>('ui').pipe(
    map(uiState=>uiState.find(state=>state.name===name)),
    filter(state=>!!state),
    distinctUntilChanged((prev, curr)=>
      prev.name===curr.name && prev.isActive === curr.isActive
    ),
    map(state=>state.isActive)
  );
}

Вот построчное описание того, что происходит:

  • Найдите состояние внутри массива по его имени
  • Отфильтровать на случай .find() возвращается undefined
  • Примените настраиваемую функцию, которая проверяет оба nameи . Если какое-либо свойство не соответствует своему предыдущему значению, оно выдаст новое значение.
  • Теперь, когда у нас есть новое значение, вернем isActive логическое.

Если кому-то это интересно, я так и сделал. Спасибо за то, что другие указали мне правильное направление:

      public getIsActive$(name: UIActionName): Observable<boolean> {
  return this.getUIAction$(name).pipe(
    map(axn => axn.isActive)).pipe(distinctUntilChanged());
}

private getUIAction$(name: UIActionName): Observable<UIAction> {
  return this.ngRedux.select<IUIState>('ui').pipe(map(state => {
    return state.actions.find(actn => actn.name === name);
  })).pipe(
    filter((axn: UIAction | undefined): axn is UIAction => axn !== undefined));
}
Другие вопросы по тегам