Search code examples
angularsignals

Why do we need two functions: update() and set() in Angular's signals?


I read about the signals in Angular and there are two methods to alter the current value: by set() and update().

Angular has adapted Signals into the framework and have started to build a set of new features that utilize Signals as their cornerstone. Using update allows us to access the current value of the signal , and set allows us to set a new value without caring about the current value.

What puzzles me is that I don't understand how both are needed (although I see that each can be used). It's clear that I can. But why?

Let's say we define an instance like so.

siggy = signal(4);

Then, we can set an absolute value using both of the following ways.

this.siggy.set(1337);
this.siggy.update((a) => 1337);

But we also can use both of those to set a relative one (alter the current).

this.siggy.set(this.siggy() + 1);
this.siggy.update((a) => a + 1);

It seem superfluous to provide multiple ways to reach the same result. Such redundancy is a sign of bad design (or possibly syntactic sugar for DX purposes). I do not in any way suggest that the great folks on Angular team made a poor design! Nor do I see any increase in smoothness. (In fact, even the Angular blog mentions the usage of this.counter.set(this.counter()+1)...)

My conclusion is that there are (edge) cases that I'm ignorant of. What am I missing?

edit

I kept on researching and discovered even more confusing facts. In addition to set() and update(), there's also mutate() (So much for Complete Guide, thank you very much). And this one can be used as below (which I intuitively did).

let siggy = signal([1,2,3]);
...
this.siggy.mutate(a => a.push(4));

It compiles. The problem is that it won't do anything: no change, no update, no nothing! Apparently, I have to do like so.

this.siggy.mutate(a => a = [...a, 4]);

But that's redundant to the others! I can understand (although I disagree) that someone may want to use set() to indicate a replacement, while keeping update() for alterations. But even then, mutate() brings no extra info as it's an update (which also sets it).

It seems like there's only siggy.alter(), siggy.change() and siggy.modify() missing. It smells fishy to me. I'm certain it's me not getting the actual reason why set/update/mutate are all required.

What is the technical reason? What can't be done with each of those?


Solution

  • TL;DR: just set is needed as you mention, update was introduced for convenience & mutate was eventually removed as essentially same as set

    You can see the full discussion in the Signals APIs RFC