ExpressionChangedAfterItHasBeenCheckedError с использованием стратегии push при отложенной загрузке маршрута и асинхронном канале - PullRequest
0 голосов
/ 28 ноября 2018

как только я переключаюсь с модуля с компонентом 1 на модуль с компонентом 2, я получаю следующую ошибку:

ОШИБКА: ExpressionChangedAfterItHasBeenCheckedError: Выражение изменилось после того, как оно было проверено.Предыдущее значение: 'ngIf: [объект объекта]'.Текущее значение: 'ngIf: [объект объекта], [объект объекта], [объект объекта], [объект объекта], [объект объекта], [объект объекта], [объект объекта], [объект объекта], [объект объекта]'

Оба модуля используют

ChangeDetectionStrategy.OnPush

Когда я подписываюсь, все нормально:

this.bookings$.pipe(takeUntil(this._destroy$)).subscribe(res => console.log(res));

Но как только я использую асинхронный канал для подписки, обнаружение изменений прекращается:

<ion-list *ngIf="bookings$ | async as bookings; else loading">
</ion-list>

Инициирование модуля / компонента 2 происходит быстрее, чем уничтожение компонента 1 при изменении маршрутов.Таким образом, компонент 1 получает изменения (фильтрованные книги), инициированные изменением даты компонента 2 перед детрой.Но это не должно быть проблемой?

service:

constructor(
  private afs: AngularFirestore
) {
  this.bookingsCollection = afs.collection<Booking>('bookings');
  this.bookingsCollection
    .snapshotChanges()
    .pipe(
      takeUntil(this._destroy$),
      map(actions => {
        return actions.map(a => {
          const data = a.payload.doc.data() as Booking;
          const id = a.payload.doc.id;
          return {id, ...data};
        });
      })
    )
    .subscribe((bookings: Booking[]) => {
      this._bookings.next([...bookings]);
      this.refreshFilteredBookings();
    });
  this.bookings$ = this._bookings
    .asObservable()
    .pipe(
      filter(bookings => bookings !== null)
    );
  this.filteredBookings$ = this._filteredBookings
    .asObservable()
    .pipe(
      filter(bookings => bookings !== null),
    );

}

private refreshFilteredBookings(): void {
  const bookings: Booking[] = JSON.parse(JSON.stringify(this._bookings.value));
  const filteredBookings: Booking[] = bookings.filter(booking =>
    moment(booking.date).isBetween(this.minDate, this.maxDate, null, '[]')
  );
  this._filteredBookings.next(filteredBookings);
}

setDate(date: Moment, type: string) {
  this.minDate = date.startOf(type as unitOfTime.StartOf).format();
  this.maxDate = date.endOf(type as unitOfTime.StartOf).format();
  if (this._bookings.value) {
    this.refreshFilteredBookings();
  }
}

компонент 1:

ngOnInit() {
   this.bookings$ = this._bookingService.filteredBookings$;
}

компонент 2:

ngOnInit() {
   this.view = 'month';
   this.date = moment().format();
   this.onDateChange();
}

onDateChange() {
   const m = moment(this.date);
   this._bookingService.setDate(m, this.view);
}

1 Ответ

0 голосов
/ 16 декабря 2018

Используете ли вы Angular 6?

Проблема может заключаться в отложенной загрузке модулей. Она не разрушает текущий компонент (компонент 1) при переходе к другому компоненту (компонент 2).поэтому asycnPipe из компонента 1 не отменяет подписку.

Во время инициализации компонента 2 он изменил значение общей службы, компонент 1 подписывается из общей службы и пытается повторно отобразить представление и вызвал эту проблему.

Я думаю, что мы можем обойти эту проблему, подписавшись на наблюдаемое из компонента и передав значение для просмотра, но это не очень хороший способ.

Другой способ можно проверить здесь


Обновление: в моем случае я меняю changeDetectionStrategy с По умолчанию на OnPush это решило мою проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...