錯誤百科

在不允許的情境中寫入訊號

當在 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,而不是儲存它:

count = signal(1);
total = computed(() => this.count() * 2);

如果該值也應該可寫入,請使用 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 或範本表達式。