1) Signals vs RxJS: Creating a Signal variable from scratch in Angular 16 and comparing it to an Observable.
With an example where we have a sidebar menu and a top menu, every time we press a button, the top menu will tell the sidebar menu to collapse:
With RxJS:
This communication is done in a service using a subject and an observable, where every time we click the button, a next is called, which passes the emitted value to the subscribed observable. The sidebar menu component will simply be subscribed and will use this property in the HTML. First, we create the Subject in the service, then we create the observable from it, and we call next to pass the emitted value:
With Signals:
This can be done simply with Signals. Signals were created in Angular to achieve better performance in certain simpler cases. They are imported from @angular/core.
You need to declare a Signal, and every time we update that signal, we call set on it. In the sidebar menu component, we just have to reference that property, and to use the signal in the HTML, we need to put parentheses around it to get its value, as this is how signals are used.
We can also perform an update, which has the added benefit of telling us the previous value. For this, we specify that it receives the previous value and its type, and with an arrow function, we indicate the new value, which is the negated new value:
There are also ways to convert observables to signals and signals to observables:
It's not that signals are a replacement for subjects, as both, along with observables, are much more powerful and have many more features, such as RxJS operators (we have much more control with RxJS). However, signals provide a simple way to work and are common with other libraries and frameworks.
RxJS is a library from Microsoft, not Angular. In contrast, Signals is a library from Angular, which provides greater control and performance, as it allows Angular to know exactly which part has changed when a state changes. This avoids having to re-render the entire component, focusing only on that specific part.
2) New simplified way to unsubscribe with takeUntilDestroyed from RxJS in Angular 16.
In Angular, it's important to unsubscribe from observables. In an example, in OnInit, we store a subscription, and in OnDestroy, we unsubscribe.
The old way was to store a variable with the subscription, and at the time of subscribing, save it in that variable and destroy that subscription in OnDestroy:
Detailed Explanation: A property of type Subscription (from RxJS) is created. This property is initialized in ngOnInit, assigning it the reference of the subscription when it is made. Then, in ngOnDestroy, the subscription is canceled. If the component hasn't defined the subscription variable, it's necessary to handle the error, either by using a question mark to check if it is defined or through a conditional.
Now, this can be done more simply, without creating OnDestroy or a subscription variable, by using the RxJS operator takeUntilDestroyed. What this does is automatically cancel the subscription when the component is about to be destroyed. It is important to inject the DestroyRef service and pass it, so it knows when the component is destroyed:
Detailed Explanation: Now, in the case where we are not unsubscribing, we add an RxJS pipe and send it a takeUntilDestroyed(), a NEW operator, which requires us to pass a destroyedRef, which is a service (from @angular/core) that we can inject into the constructor.
Example: In a sidebar service, it listens for a button click in the navbar component. With takeUntilDestroyed(), it unsubscribes only when the component is destroyed, avoiding multiple subscriptions. In this case, we always want to listen to whether the button has been pressed or not; therefore, we only want to unsubscribe if the component is destroyed.
This is important to do, as otherwise, it will be listening even if we are in other components, and it will only unsubscribe if we close the app since the component is destroyed. This is crucial because if it is always active, when navigating through page components, for example, in the first navigation, it subscribes, then we navigate to another page, and when we return to the first page, it would be a second subscription, resulting in two active subscriptions. Thus, it is important to unsubscribe.
An important note: when we subscribe to an HTTP request, it is not necessary to unsubscribe, as this is done automatically.
3) Effect of a Signal in Angular. Listening for changes in a Signal.
In an example, we have a Signal that returns a boolean and in a method below, it updates with an update:
Imagine you want to be alerted whenever the signal changes, but it changes from many places, not just from this method. If we want to do something whenever it changes, we can do this with an effect. This function takes a signal and checks if it changes to automatically execute the method within the effect:
With this, for example, instead of a console log, we can save the value in local storage and instantiate it with that value. This is especially useful when working with code that we do not know and are unsure how many places it is being modified from.
— Notes based on the Angular course from EfisioDev —
Top comments (1)
Hi Samira Awad,
Top, very nice and helpful !
Thanks for sharing.