Reputation: 1107
I have a shared service with signals for everything regarding layout. This is in an external library.
In a component within an application I want to set a signal in this shared service. The problem is that you need to set allowSignalWrites
to true in this case on the effect.
The official documentation from Angular also explains that the untracked function can be used to call external code.
Would this be a good alternative to setting allowSignalWrites
to true? Because the comment on that property doesn't encourage the use of it.
// signal in the application (invoice detail page)
readonly #invoice = this.#localStore.invoice;
// shared service for the layout (note that the layout is shared accross pages)
readonly #layout = inject(SharedLayoutService);
effect(() => {
if (this.#invoice()) {
const subtitle = `Invoice${this.#invoice().reference}`;
untracked(() => this.#layout.subTitle.set(subtitle); });
});
});
Upvotes: 1
Views: 455
Reputation:
effect()
is a consumer of every signal it reads.
Signals (producers) notify their consumers about every change. After that, consumers will re-read the values of producers (eventually).
To read values, effect()
runs the function you passed as the first argument.
It means, that effect()
will execute that function every time the related signals are modified.
If you modify involved signals inside the function you passed to effect()
, it will cause an endless loop. Some signals are derived (computed()
), so you might modify signals you read indirectly:
a = signal(0);
b = signal(0);
c = computed(() => a() + b());
constructor() {
effect(() => {
if (this.c() > 1) {
this.a.update(a => a * 2); // endless loop, because c is changed
}
});
}
It is just one of the reasons why documentation says that you should avoid effect()
.
Now we can see the difference between allowSignalWrites
and untracked()
:
allowSignalWrites
you are saying "I know what I'm doing, no bad things will happen, and I want my effect to keep listening to every signal it reads - they will not be modified in this effect".untracked()
you are saying "I can not be sure that it will not cause indirect modifications of the signals this effect reads, so please do not listen to the changes it might cause (do not track them)".As you can see, untracked()
is more safe to use, allowSignalWrites
is only for the cases when you can clearly see that no indirect changes will happen.
But even with untracked()
you should be sure that by modifying this signal you will not trigger ExpressionChangedAfterItHasBeenChecked
(yes, it is possible).
Upvotes: 2