Angular ExpressionChangedAfterItHasBeenCheckedError 오류
Angular는 변경 감지 사이클을 통해 표현식을 바인딩하는데 때때로 ExpressionChangedAfterItHasBeenCheckedError와 같은 바인딩 오류가 발생합니다.
일반적으로 다음과 같은 경우에 많이 발생합니다.
1. Angular의 뷰 라이프사이클 후킹 메소드 안에서 모델 데이터를 변경한 경우
2. Angular의 Change Detection이 실행된 후에 모델 데이터를 변경한 경우
3. 자식 컴포넌트에서 이벤트를 트리거하여 부모 컴포넌트의 속성을 변경한 경우
이 오류를 해결하기 위해 Angular는 몇 가지 방법을 제공합니다.
1. ChangeDetectionStrategy 설정
컴포넌트의 ChangeDetectionStrategy를 OnPush로 설정하여 변경 감지 전략을 변경할 수 있습니다. 이렇게 하면 컴포넌트의 변경 감지가 자동으로 실행되지 않고, 수동으로 변경 감지를 실행해야 합니다. 이 방법은 컴포넌트가 불필요하게 자주 업데이트되는 것을 방지할 수 있습니다.
import { Component, ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'app-my-component',
template: `
<div>{{ myData }}</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyComponent {
myData: string;
constructor(private myService: MyService) {}
ngAfterViewInit() {
this.myService.getData().subscribe(data => {
this.myData = data;
});
}
}
2. setTimeout 사용
변경 감지가 완료된 후에 DOM 변경을 실행하려면, setTimeout 함수를 사용하여 변경 감지를 마무리한 후에 변경을 실행하도록 지연시킬 수 있습니다.
import { Component, AfterViewInit } from '@angular/core';
@Component({
selector: 'app-my-component',
template: `
<div>{{ myData }}</div>
`
})
export class MyComponent implements AfterViewInit {
myData: string;
constructor(private myService: MyService) {}
ngAfterViewInit() {
this.myService.getData().subscribe(data => {
setTimeout(() => {
this.myData = data;
});
});
}
}
3. ChangeDetectorRef 사용
ChangeDetectorRef를 사용하여 수동으로 변경 감지를 실행하고, 변경 감지 이후에 변경을 실행할 수 있습니다.
import { Component, AfterViewInit, ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'app-my-component',
template: `
<div>{{ myData }}</div>
`
})
export class MyComponent implements AfterViewInit {
myData: string;
constructor(private myService: MyService, private cdr: ChangeDetectorRef) {}
ngAfterViewInit() {
this.myService.getData().subscribe(data => {
this.myData = data;
this.cdr.detectChanges(); // 변경 감지 수동 실행
});
}
}
4. ngOnChanges 사용
ngOnChanges 라이프사이클 후킹 메소드를 사용하여 변경 감지 이후에 변경을 실행할 수 있습니다.
import { Component, OnChanges, SimpleChanges } from '@angular/core';
@Component({
selector: 'app-my-component',
template: `
<div>{{ myData }}</div>
`
})
export class MyComponent implements OnChanges {
myData: string;
ngOnChanges(changes: SimpleChanges) {
if (changes.myData) {
this.myData = changes.myData.currentValue;
}
}
ngAfterViewInit() {
this.myService.getData().subscribe(data => {
this.myData = data;
});
}
}
5. ViewChild 사용
ViewChild 데코레이터를 사용하여 컴포넌트 또는 디렉티브의 참조를 가져와서, ngAfterViewInit 메서드에서 변경을 실행할 수 있습니다.
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { MyDirective } from './my.directive';
@Component({
selector: 'app-my-component',
template: `
<div myDirective></div>
`
})
export class MyComponent implements AfterViewInit {
@ViewChild(MyDirective) myDirective: MyDirective;
ngAfterViewInit() {
this.myService.getData().subscribe(data => {
setTimeout(() => {
this.myDirective.doSomething(data);
});
});
}
}
이러한 방법 중 하나를 사용하여 ExpressionChangedAfterItHasBeenCheckedError 오류를 방지할 수 있습니다. 그러나 모든 경우에 이 오류를 완전히 예방하기는 어려울 수 있으며, 이 오류가 발생하는 경우 대부분은 Angular의 변경 감지 시스템의 작동 방식에 대한 이해가 필요합니다.
'개발 > front-end' 카테고리의 다른 글
angular 별도 라이브러리 없이 tree 기능 구현 (0) | 2023.04.01 |
---|---|
angular 이미지 로딩 속도 개선 (0) | 2023.04.01 |
angular 개발 최적화 방법 (0) | 2023.04.01 |
SPA기반 Front 카카오 로그인 api 연동 (0) | 2023.02.24 |
SPA기반 Front 구글 로그인 api 연동 (0) | 2023.02.24 |