Fel
Fel

Reputation: 4818

ngrx action triggering ExpressionChangedAfterItHasBeenCheckedError exception

I'm starting an Angular application that uses ngrx for its state management and I've come across a problem that has puzzled me a bit:

One of the UI actions is to block the screen with a loader, and there is another one to unblock it:

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

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

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

The associated reducer only triggers a flag between true or false depending on the action:

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

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

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

  ...

I subscribe to this state flag in the main app's component to show/hide the UI blocker:

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

I'm using the distinctUntilChanged rxjs operator to discard equal flag values because the block/unblock action can be dispatched from several components at the same time:

UI actions

This is the component in the HTML template that blocks the UI (I use PrimeNG BlockUI):

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

In my opinion, everything should work fine, but when I run the app I get the following error:

Exception

I can solve it easily adding a delay(1) rxjs operator to the state subscription, but I'd like to know why the exception is fired, as I can't find the reason...

Many thanks!

Upvotes: 2

Views: 193

Answers (2)

Fel
Fel

Reputation: 4818

As suggested by @kvetis, I fetched the data in the parent component and saved it in the app store to render it easily from the child components and the Angular exception is gone.

Upvotes: 0

kvetis
kvetis

Reputation: 7341

It is not question of how you react to the action but when you dispatch the action. The dispatch probably happens after some of the code has been already checked (somewhere in parent component), possibly in ngOnInit or ngOnChanges or it reacts to input. It is hard to tell because you did not include the code where you dispatch, but I'm certain that is the problem.

Upvotes: 1

Related Questions