computed나 템플릿을 평가하는 동안 set 또는 update로 시그널에 값을 쓰면 Angular가 이 오류를 발생시킵니다. 두 컨텍스트는 시그널을 읽기만 해야 하므로 여기서 쓰기를 수행하면 계산 도중 상태가 바뀝니다.
오류 메시지에 두 경우 중 어느 상황인지 표시됩니다.
computed에서는 시그널에 값을 쓸 수 없습니다
computed는 부수 효과 없이 다른 시그널에서 값을 도출해야 합니다.
count = signal(1);
total = signal(0);
doubled = computed(() => {
this.total.set(this.count() * 2); // not allowed
return this.count() * 2;
});
값이 다른 시그널에만 의존한다면 별도로 저장하지 말고 그 자체를 computed로 만드세요.
값을 직접 쓸 수도 있어야 한다면 linkedSignal을 사용하고, 쓰기가 변경에 따른 부수 효과라면 effect를 사용하세요.
linkedSignal 계산 안에서 값을 쓸 때도 같은 오류가 발생합니다.
Angular가 템플릿을 렌더링하는 동안에는 시그널에 값을 쓸 수 없습니다
템플릿 표현식은 렌더링 중 실행되므로 템플릿에서 호출하는 메서드도 시그널에 값을 쓰면 안 됩니다.
@Component({
selector: 'app-example',
template: '<p>{{ label() }}</p>',
})
export class Example {
views = signal(0);
label() {
this.views.update((v) => v + 1); // not allowed
return `Viewed ${this.views()} times`;
}
}
실제로 변경이 일어나는 위치로 쓰기 작업을 옮기세요. 이벤트 리스너, 라이프사이클 훅, 출력 핸들러, 이펙트 함수에서는 시그널에 값을 쓸 수 있습니다.
untracked 사용하기
untracked로 감싼 쓰기 작업은 오류를 발생시키지 않습니다. 의도적인 쓰기이며 다른 곳으로 옮길 수 없을 때만 사용하세요. untracked 안에서 읽은 시그널도 추적되지 않는다는 점에 유의하세요.
오류 디버깅하기
스택 트레이스는 set 또는 update 호출을 가리킵니다. 여기서 해당 호출을 실행한 computed, linkedSignal, 템플릿 표현식을 찾으세요.