ExpressionChangedAfterItHasBeenCheckedError: Выражение изменилось после его проверки - Как обновить шаблон после изменения наблюдаемого значения - PullRequest
1 голос
/ 13 июня 2019

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

this.navigationSelected$ = this.store.pipe(select(currentlySelectedNavigation));

this.navigationSelected$.subscribe(res => {
  ...
});

с ngIf в зависимости от этого наблюдаемого значения внутри шаблона:

<profile-navigation *ngIf="(navigationSelected$ | async) == navigationLayout[0].location"></profile-navigation>

Всякий раз, когда изменяется значение navigationSelected $, выдается:

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: [object Object]'. Current value: 'ngIf: false'.

и шаблон не обновляется. Мне удалось обойти это, запустив cdRef.detectChanges (); в конце подписки. Он работает нормально, но ошибка все еще выдается, плюс, как уже упоминалось, это похоже на взлом.

Как лучше всего достичь того, что я пытаюсь сделать?

1 Ответ

2 голосов
/ 13 июня 2019

Всякий раз, когда изменяется значение navigationSelected $, выдается следующее:

Ошибка означает, что значение изменилось дважды.

Когда у вас есть эти ошибки в селекторе, ономожет быть очень трудно исправить их.В этом нет ничего плохого.Проблема в том, что хранилище меняет состояние до и после рендеринга представления, и это, вероятно, означает, что существует диспетчеризация, которая должна произойти после вызова setTimeout().

Проблема в том, что это делает некоторыедругое место в вашем исходном коде зависит от изменения состояния, чтобы защитить представление от появления ошибки.Это не идеально.

Альтернативой является выдача значения с использованием EventEmitter.

<profile-navigation *ngIf="(navigationSelectedSafe$ | async) == navigationLayout[0].location"></profile-navigation>

public navigationSelectedSafe$ = new EventEmitter<any>(true); // must be true

this.navigationSelected$.subscribe(res => navigationSelectedSafe$.emit(res));

Когда вы используете EventEmitter(true), он будет выдавать значения после setTimeout(), который защищает видот ошибок изменений.

Вы также можете искать вокруг вашего исходного кода для мест, где вы используете @Output(), и посмотреть, если изменение его на EventEmitter(true) решит проблему.

Обычно, когда вы видите эту ошибку на селекторе.Это означает, что вы выполняете большую работу, связанную с состоянием, за пределами представлений.Компонент, который должен передать, что что-то изменилось, должен использовать @Output(), но если этот компонент отправляет, то он обходит процесс просмотра.Здесь вы сталкиваетесь с этими проблемами.

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