ChangeDetectorRefで変更検知を手動で実行する。は?【Angular】

 

 

ngOninit で時間のかかる非同期処理を行い、

ブラウザの開発者モードで表示した際に、

コンソールに下記エラーが発生しました。(画面は正常に動いている。)

1
ExpressionChangedAfteritHasBeenCheckedError;

何が起こっていたのか

Angular の変更検知のサイクルの一つである、

コンポーネントのライフサイクルフックが終わった後に、(ngOninit など)

非同期処理のデータが流れてきたため、エラーが発生していたと思われます。

でも、Angular にとって、非同期なデータが画面描画後に来ることは普通のことな気がしていて、

よく分からないなと言う感想です。

ただ、今回の状況を振り返ると、

ngAffterViewInit でエラーが起きていました。

ngAffterViewInit は一度しか呼ばれないのが通常な為、

今回のエラーが発生したと思われます。

 

解決方法は ChangeDetectorRef.detectChanges()

ngAffterViewInit の該当処理の後に、

ChangeDetectorRef.detectChanges()を入れることで、

ブラウザ側のエラーが解消しました。

 

ChangeDetectorRef について調べた

ChangeDetectorRef.detectChanges()を追加することで、回避しているのですが、

どういうクラスなのか確認していきます。

ChangeDetectorRef には下記メソッドがあります。

  • markForCheck
  • detach
  • detectChanges
  • checkNoChanges
  • reattach

まず、detach,reattach はそれぞれ変更検知を止める処理と、

動かす処理になります。

そもそも、変更検知って何かを例えると、

人間の感覚器官のようなものだと思います。

その為、detach すると視覚も聴覚も触覚も全てが無くなるが、

意識はあるようなイメージです。怖すぎ笑

 

checkNoChanges は前回の状態から差異がないことを確認するメソッドです。

差異がある場合、ブラウザの開発者モードでエラーを出力するみたいです。

 

markForCheck は次回の変更検知の際に、対象のコンポーネントに対して、

変更検知のサイクルを動かしたいときに使います。

変更検知のサイクルを自動ではなく、手動で管理したい際に使うものみたいですね。

 

変更検知を手動で動かしたい場合は、コンポーネントの設定に、下記を追加することで、

Angular の変更検知を手動で動かせるようになるようです。(デフォルトは自動になります)

1
changeDetection: ChangeDetectionStrategy.OnPush;

detectChanges とは

detectChangesは変更検知のサイクルを再度実行する処理になります。
今回のエラーが解消したのも、(ngAffterViewInitが意図せず2回動くことによるエラー)
もう一度、変更検知のサイクルを意図的に動かしたからと言うことになリマス。
Licensed under CC BY-NC-SA 4.0
Last updated on Sep 10, 2023 03:39 UTC
Built with Hugo
Theme Stack designed by Jimmy