ExpressionChangedAfterItHasBeenCheckedError in Angular - Cosa, perché e come risolverlo?

ExpressionChangedAfterItHasBeenCheckedError è senza dubbio il mio errore preferito nelle applicazioni angolari.

Ho riscontrato questo errore molto quando ho iniziato a lavorare con Angular. Secondo GitHub, così fanno molti altri.

Quando verrà generata ExpressionChangedAfterItHasBeenCheckedError?

I motivi più comuni sono:

  1. Stai eseguendo il codice in AfterViewInit che spesso si verifica quando lavori con ViewChild, poiché non è definito fino a quando non viene chiamato AfterViewInit.
  2. Stai manipolando direttamente il DOM (ad es. Usando jQuery). L'angolare non può sempre rilevare questi cambiamenti e reagire correttamente.
  3. Può anche accadere a causa delle condizioni di gara quando si chiamano funzioni all'interno del modello HTML.

Che cos'è ExpressionChangedAfterItHasBeenCheckedError cercando di avvisarmi?

ExpressionChangedAfterItHasBeenCheckedError viene generato quando un'espressione nel tuo HTML è cambiata dopo che Angular lo ha verificato (è un errore molto espressivo).

Questo errore viene generato solo in modalità di sviluppo e per una buona ragione; è spesso un segno che dovresti refactoring il tuo codice, poiché Angular ti avverte che questo cambiamento nella tua espressione non verrà rilevato quando si abilita la modalità di produzione!

Uno dei motivi per cui la modalità di produzione è più veloce della modalità di sviluppo, è che Angular ignora alcuni controlli (ad esempio il rilevamento delle modifiche dopo AfterViewInit) che vengono eseguiti in modalità di sviluppo. Ciò significa che il codice che funzionerà correttamente nella modalità di sviluppo non funzionerà nella modalità di produzione.

Ecco un esempio che funzionerebbe bene in modalità di sviluppo ma non in modalità di produzione:

Come correggere ExpressionChangedAfterItHasBeenCheckedError

Fix one

Come soluzione rapida, setTimeout o ChangeDetectorRef vengono spesso utilizzati per far scomparire l'errore.

Quest'ultimo è migliore, poiché con ChangeDetectorRef viene verificata la vista dei componenti e i relativi elementi figlio. D'altra parte, setTimeout farà sì che Angular verifichi la presenza di modifiche nell'intera applicazione, il che è molto più costoso.

Risolvi due

A volte, l'errore è ancora più facile da correggere: basta spostare il codice su OnInit.

A meno che non si debba fare affidamento su ViewChild o se un codice deve essere eseguito solo dopo che Angular ha inizializzato completamente la vista di un componente, il passaggio a OnInit risolverà il problema.

Questo perché Angular eseguirà il rilevamento delle modifiche dopo OnInit sia in modalità di produzione che di sviluppo.

Risolvi tre

Non ti piace la magia angolare e come rileva i cambiamenti? Disattiva semplicemente il rilevamento automatico delle modifiche nel componente e comunica a Angular quando deve rilevare le modifiche.

ChangeDetectionStrategy può essere specificato in un componente decoratore su OnPush. Ora, Angular rileverà automaticamente le modifiche di input e il resto dipende da te.

Mentre c'è meno magia coinvolta abilitando la strategia OnPush, ottieni anche prestazioni migliori in quanto c'è meno lavoro da fare per Angular. Questo può essere utile per ottimizzare componenti grandi e complessi.

D'altra parte, devi assicurarti di lasciare che Angular raccolga le modifiche. In caso contrario, di solito verranno visualizzati errori dell'interfaccia utente (ad esempio un modale che non scompare).

Quindi, non applicarlo troppo avidamente senza controllare accuratamente il componente.

Conclusione

Ora dovresti essere in grado di capire quando e perché si verifica il famigerato ExpressionChangedAfterItHasBeenCheckedError.

Come puoi vedere, esistono diversi modi per gestire questo errore. Assicurati solo di risolvere il vero problema di fondo, invece di aggirare il problema.