ngrx 操作触发 ExpressionChangedAfterItHasBeenCheckedError 异常

ngrx action triggering ExpressionChangedAfterItHasBeenCheckedError exception

我正在启动一个使用 ngrx 进行状态管理的 Angular 应用程序,我遇到了一个让我有点困惑的问题:

其中一个UI动作是用loader挡屏,还有一个是解锁:

import { createAction } from "@ngrx/store";

export const blockUI = createAction("[UI] Block UI");

export const unblockUI = createAction("[UI] Unblock UI");

关联的 reducer 仅触发 truefalse 之间的标志,具体取决于操作:

export const uiReducer = createReducer<UiState>(initialState,
  ...

  on(blockUI, (state) => ({ ...state, blockUi: true })),

  on(unblockUI, (state) => ({ ...state, blockUi: false })),

  ...

我在主应用程序的组件中订阅了此状态标志以 show/hide UI 拦截器:

  this.store.pipe(
    select((state) => state.ui.blockUi),
    distinctUntilChanged()
  ).subscribe(
    (blockUi) => {
      console.log("Block UI: ", blockUi);
      this.loading = blockUi;
    }
  );

我正在使用 distinctUntilChanged rxjs 运算符来丢弃相等的标志值,因为 block/unblock 操作可以同时从多个组件调度:

这是 HTML 模板中阻止 UI 的组件(我使用 PrimeNG BlockUI):

  <!-- Component to block/unblock the UI -->
  <p-blockUI [blocked]="loading">
    <div class="divCenterHV">
      <p-progressSpinner></p-progressSpinner>    
    </div>
  </p-blockUI>

在我看来,一切正常,但是当我 运行 应用程序时,出现以下错误:

我可以很容易地解决它添加一个 delay(1) rxjs 运算符到状态订阅,但我想知道为什么会触发异常,因为我找不到原因...

非常感谢!

这不是你如何对动作做出反应的问题,而是你何时派发动作的问题。分派可能发生在已经检查了一些代码(父组件中的某处)之后,可能在 ngOnInit 或 ngOnChanges 中,或者它对输入做出反应。很难说,因为您没有在发送时包含代码,但我确定这就是问题所在。

按照@kvetis 的建议,我在父组件中获取数据并将其保存在应用程序商店中以便从子组件轻松呈现它并且 Angular 异常消失了。