Listen to value updates using effect() in HTML tags. However, this method is not equivalent to listening to changes of an Observable or BehaviorSubject in RxJS. The effect() method with Signals is mainly used for updating logging, saving data to local storage, or updating the canvas. By default, you cannot update a signal within the effect().
For instance, we can create a component that logs when the price is updated. In the constructor, we add the effect() to display the updated price. In the HTML, we create a button to update the price.
“`typescript
@Component({…})
export class SignalsGetUpdatesComponent {
price = signal
priceUpdated = signal
constructor() {
effect(() => {
console.log(`Price updated ${this.price()}`);
});
}
updatePrice() {
this.price.update((price) => price + 30);
this.priceUpdated.set(true);
setTimeout(() => {
this.priceUpdated.set(false);
}, 2000);
}
}
“`
“`html
Get updates
Add {{30 | currency: ‘EUR’}} to the price
of {{10 | currency: ‘EUR’}} and notify.
Is price updated: {{priceUpdated() ? “๐” : “๐”}}
Price: {{price() | currency:’EUR’}}
“`
In this case, we update the priceUpdated signal in the updatePrice() method while updating the price. In RxJS with a BehaviorSubject, you could have done that in the subscribe() method. It is a matter of preference.
If you are aware of the risks of creating an infinite loop by updating signals in the effect(), you can enable it by passing a second parameter { allowSignalWrites: true }.
“`typescript
@Component({…})
export class SignalsGetUpdatesEffectUpdateComponent {
price = signal
priceUpdated = signal
constructor() {
effect(() => {
console.log(`Price updated ${this.price}`)
this.priceUpdated.set(true)
setTimeout(() => {
this.priceUpdated.set(false)
}, 2000)
}, { allowSignalWrites: true })
}
updatePrice() {
this.price.update(price => price + 30)
}
}
“`
“`html
Get updates and overwrite signal in effect
Add {{30 | currency: ‘EUR’}} to the price
of {{10 | currency: ‘EUR’}} and notify.
Is price updated: {{priceUpdated() ? “๐” : “๐”}}
Price: {{price() | currency:’EUR’}}
“`
The effect will run when the component is initialized, similar to the ngOnInit hook.
Now let’s talk about computations. A computation is used when calculating or concatenating strings based on changing values. Here’s how you can get the value from a computation in Signals:
“`typescript
// Signal
getDoubleCount() {
console.log(this.doubleCount())
}
// BehaviorSubject
getDoubleCount() {
this.doubleCount.subscribe((value) => console.log(value))
}
“`
Getting the double-count value is less straightforward with BehaviorSubject compared to Signals because you need to ensure that the subscription is removed when it’s no longer needed.
With Signals, Angular handles many things for you, more than using RxJS. With RxJS, you often need to handle subscriptions yourself, whereas with Signals, Angular takes care of it for you.
For example, to clean up subscriptions in RxJS, you need to use the `takeUntil` operator. Here’s an example:
“`typescript
// Inside a component class
// …
destroy$ = new Subject
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
getDoubleCount() {
this.doubleCount.pipe(takeUntil(this.destroy$)).subscribe((value) => console.log(value));
}
// …
“`
With Signals, you can achieve the same result without explicitly managing subscriptions:
“`typescript
typs
getDoubleCount() {
this.doubleCount.subscribe((value) => console.log(value));
}
“`
Signals bring simplicity when working with reactivity. If you’re familiar with Vue, Signals have a similar way of handling reactive properties.
For example, let’s update a first name and display the full name using computed():
“`typescript
@Component({…})
export class SignalsComputeValueComponent {
firstName = signal(‘Bart’);
lastName = signal(‘The Great’);
fullName = computed(() => this.firstName() + ‘ ‘ + this.lastName());
changeFirstName() {
this.firstName.set(‘Ray’);
}
}
“`
“`html
Get updates and overwrite signal in effect
Firstname: {{ firstName() }}
Lastname: {{ lastName() }}
Fullname computation: {{ fullName() }}
“`
As you can see, the fullName property in the computed() method merges two strings. When the firstName is updated, the fullName is automatically updated and reflected in the view. It’s that simple!
Now you have a good understanding of how to use Angular Signals. Start using them and enjoy their simplicity!
If you have any questions or feedback, feel free to send me a message. You can reach me on Twitter (@DevByRayRay). I’m always open to discussing and helping out!
Source link