ExpressionChangedAfterItHasBeenCheckedError in Angular - Quoi, Pourquoi et comment y remédier?

ExpressionChangedAfterItHasBeenCheckedError est sans aucun doute mon erreur préférée dans les applications angulaires.

J'ai souvent rencontré cette erreur lorsque j'ai commencé à travailler avec Angular. Selon GitHub, beaucoup d'autres le font aussi.

Quand ExpressionChangedAfterItHasBeenCheckedError sera-t-il lancé?

Les raisons les plus courantes sont:

  1. Vous exécutez du code dans AfterViewInit, ce qui arrive souvent lorsque vous utilisez ViewChild, car il n'est pas défini jusqu'à l'appel de AfterViewInit.
  2. Vous manipulez le DOM directement (par exemple, en utilisant jQuery). Angular ne peut pas toujours détecter ces changements et réagir correctement.
  3. Cela peut également arriver en raison de conditions de concurrence lorsque vous appelez des fonctions dans votre modèle HTML.

Qu'est-ce que ExpressionChangedAfterItHasBeenCheckedError tente de me prévenir?

ExpressionChangedAfterItHasBeenCheckedError est renvoyée lorsqu'une expression de votre code HTML a été modifiée après que Angular l'ait vérifiée (il s'agit d'une erreur très expressive).

Cette erreur est uniquement générée en mode développement et pour une bonne raison; c'est souvent le signe que vous devez refactoriser votre code, car Angular vous avertit que ce changement d'expression ne sera pas pris en compte lors de l'activation du mode de production!

L'une des raisons pour lesquelles le mode de production est plus rapide que le mode de développement est qu'Angular ignore certaines vérifications (par exemple, la détection de changement après AfterViewInit) effectuées en mode de développement. Cela signifie que le code qui fonctionnera bien en mode développement ne fonctionnera pas en mode production.

Voici un exemple qui fonctionnerait bien en mode développement mais pas en mode production:

Comment réparer une erreur ExpressionChangedAfterItHasBeenCheckedError

Fixer un

En guise de solution rapide, setTimeout ou ChangeDetectorRef sont souvent utilisés pour faire disparaître l'erreur.

Ce dernier est meilleur, car avec ChangeDetectorRef, la vue du composant et ses enfants sont vérifiés. Par ailleurs, avec setTimeout, Angular vérifiera l’application dans son ensemble pour y trouver des modifications, ce qui est beaucoup plus coûteux.

Fixe deux

Parfois, l'erreur est encore plus facile à corriger - déplacez simplement votre code vers OnInit.

Sauf si vous devez vous fier à ViewChild ou si un code ne doit être exécuté qu'une fois que Angular a entièrement initialisé la vue d'un composant, le fait de passer à OnInit résoudra votre problème.

En effet, Angular effectuera la détection des modifications après OnInit en mode de production et en mode de développement.

Fix trois

Vous n’aimez pas la magie angulaire et comment elle détecte les changements? Désactivez simplement la détection automatique des modifications dans votre composant et indiquez vous-même à Angular quand elle devrait détecter les modifications.

ChangeDetectionStrategy peut être spécifié dans un décorateur de composant sur OnPush. À présent, Angular ne détectera que les modifications d’entrée automatiquement et le reste appartient à vous.

Même si l'activation de la stratégie OnPush est moins magique, vous améliorez également les performances, car Angular a moins de travail à faire. Cela peut être utile pour optimiser des composants volumineux et complexes.

D'autre part, vous devez vous assurer que Angular prend en charge les modifications. Si vous ne le faites pas, vous verrez généralement des erreurs d'interface utilisateur (par exemple, un modal ne disparaissant pas).

Par conséquent, n'appliquez pas cette méthode trop rapidement sans vérifier soigneusement votre composant.

Conclusion

Vous devriez maintenant être en mesure de comprendre quand et pourquoi l’infâme ExpressionChangedAfterItHasBeenCheckedError se produit.

Comme vous pouvez le constater, il existe plusieurs façons de traiter cette erreur. Assurez-vous simplement que vous résolvez réellement le vrai problème sous-jacent, au lieu de le contourner.