Angular7 + REDUX: ошибка: «ExpressionChangedAfterItHasBeenCheckedError: выражение изменилось после проверки.

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

У меня есть архитектура redux в angular7, и я просто отправляю действия для изменения логического значения в моем хранилище redux.

В моем app.component.ts я подписываюсь на это «обещание» из хранилища redux и на основе его значения меняю локальную переменную, которую я привязываю к элементу HTML с помощью ngClass, например:

В разметке HTML в app.component.html:

<mat-progress-bar class="loadingSpinner" 
[ngClass]="hiddenSpinner" mode="indeterminate"></mat-progress-bar>

В моем контроллере в app.component.ts:

  ngOnInit() {
  this.loadingSubscription = this.isLoading.subscribe(data => {
    if(data == true){this.hiddenSpinner = "" } else { this.hiddenSpinner = "hiddenSpinner"}
    })}

Мое действие Redux:

case START_LOADING: if(INITIAL_STATE.isLoading == false) 
{ return startLoading(state, action) } else { return };

Но ошибка сохраняется!

Ошибка позволяет мне на 100% быть уверенным, что это из-за конкретной переменной.

Ошибка не появляется, если я просто отключу этот элемент html.


person SebastianG    schedule 06.11.2018    source источник
comment
Я предполагаю, что isLoading изменяется, пока выполняется обнаружение изменений. Может попробовать this.loadingSubscription = this.isLoading.pipe(delay(0)).subscribe(...). (Я думаю, что это может вызвать другое обнаружение изменений, поэтому используйте его с осторожностью).   -  person sloth    schedule 06.11.2018
comment
Также обратите внимание, что во многих случаях можно игнорировать эту ошибку.   -  person sloth    schedule 06.11.2018


Ответы (1)


ExpressionChangedAfterItHasBeenCheckedError является очень понятным ожиданием, что означает, что что-то изменилось во время работы Change Detector Cyclone (в основном в дочернем компоненте). В вашем случае это hiddenSpinner.

Вариант 1. Чтобы решить эту проблему, вы можете использовать setTimeout

 ngOnInit() {
  this.loadingSubscription = this.isLoading.subscribe(data => {
   setTimeout(()=>{

    if(data == true){
        this.hiddenSpinner = "" 
    } else { 
         this.hiddenSpinner = "hiddenSpinner"}
      });
    })}

Вариант 2: я бы рекомендовал использовать этот подход

 ngOnInit() {
  this.loadingSubscription = this.isLoading.subscribe(data => {
   Promise.resolve(null).then(()=>{

    if(data == true){
        this.hiddenSpinner = "" 
    } else { 
         this.hiddenSpinner = "hiddenSpinner"}
      });
 })}

Примечание: код пишется непосредственно в редакторе stackoverflow, поэтому возможна опечатка или синтаксическая ошибка. Пожалуйста, поправьтесь.

person Sunil Singh    schedule 06.11.2018
comment
Спасибо за это - похоже, что ваш второй подход сработал и научил меня ценной вещи в процессе. Я буду продолжать тестирование до конца дня и напишу, если это действительно не сработало и пометил это как ответ. Спасибо! - person SebastianG; 06.11.2018