當在 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`;
}
}
把寫入移到變更實際發生的地方。在事件監聽器、生命週期勾點、輸出處理常式與 effect 中允許寫入訊號。
使用 untracked
以 untracked 包住的寫入不會拋出錯誤。只有在寫入是刻意的且無法移動時才使用它,並請記住,在 untracked 內讀取的訊號同樣不會被追蹤。
除錯方式
堆疊追蹤會指向 set 或 update 呼叫。從該處找出呼叫它的 computed、linkedSignal 或範本表達式。