Angular Signals Explained: A Comprehensive Guide for Developers
What are Angular signals?
Angular signals are a new feature introduced in Angular 17. They provide a fresh approach to handling reactive data in your applications. Signals act as data streams you can read from and write to. Essentially, they simplify dealing with reactive values.
Key points about signals:
- Wrapper Around Values: A signal wraps around a value and notifies interested consumers when that value changes. You can think of it as a reactive container.
- Readable and Writable: Signals can be either read-only or writable. You can read a signal’s value using its getter function. Writable signals allow you to update their value directly. Signals can hold basic primitive values to intricate data structures.
Why Signals?
- Performance: Traditionally, when something changes in one part of your Angular app, Angular checks all other parts to see if they’re affected. Signals improve efficiency by allowing targeted checks only where needed.
- Testing Made Easier: Signals provide a predictable way to trigger change detection, making testing more reliable.
How to create Signals
We can create signals using signal()
method and signals must contain an initial value 👇
How to Read and Update Signal Values
Signal values are read through getter functions like : firstSignal()
, the reason for this is to detect at what places signals are used
Computed Signals
Computed signals are read-only and derive their value from other signals. These signals are defined using the computed
function, where you specify the derivation logic
The z
signal depends on the x
signal and y
signal. Whenever the x or y updates, Angular knows that z
can update as well.
Some Key points About Computed
Signals
Computed
signals are not Writable (Means that are ReadOnly Signals)
- We cannot directly assign value to computed signals.
- If we execute
z.set(12)
, we’ll get a compilation error because z is not a WritableSignal.
Computed
signals are both lazily evaluated and memoized.
z's
derivation function does not run to calculate its value until the first time you read z
. The calculated value is then cached, and if you read z
again, it will return the cached value without recalculating.
Effect’s
Signals play a crucial role in alerting interested consumers to changes. Conversely, an effect denotes an operation that triggers whenever there is a change in one or more signal values. To create an effect, you can utilize the “effect function.”
Effects
are functions that execute in response to signal changes. They initially run at least once, and any subsequent signal value updates will cause them to run again.
During the change detection process, the effects always execute asynchronously.
Use cases for effects
In a variety of use-case scenarios, an effect can be extremely beneficial.
-
Logging Data Updates:
- “Effects provide a way to log signal value changes for debugging or tracking. You can access the new value within the effect function and log it to the console, a file, or a monitoring service.”.
-
Data Persistence:
- “Effects can be utilized to initiate actions associated with data persistence. For instance, you may need to store the updated cart quantity (which is stored in a signal) in local storage whenever the quantity changes. This guarantees that the cart data remains intact even after a page refresh.”
-
Side Effects Based on Signal Changes:
- Updating other UI components based on the new signal value, for example, highlighting a button depending on user selection.
- Making API calls to fetch additional data or update a remote server when a signal changes, for example, fetching product details after selecting a product from a list.
Real-world scenarios where we can utilize signals
- E-commerce Shopping Cart with Automatic Updates:
Imagine you’re building an e-commerce application. Traditionally, managing the shopping cart state and updating the UI accordingly might involve:
- Storing cart items in a component property or service.
- Manually updating the component’s view whenever an item is added, removed, or quantity is changed.
- Using techniques like ngOnChanges or ChangeDetectorRef.detectChanges to trigger change detection and update the UI.
- This approach may present challenges, particularly when multiple components need to reflect the state of the cart. (e.g., summary, checkout page).
- To address this issue, we can make use of signals.
- Sure, you can find the code for the following example here: Cart component
- Some other examples where signals might be useful are
- Real-time chat application,
- Dynamic theming
- Logging and analytics for monitoring changes
Let’s focus on the issues that Angular typically addresses using signals.
Performance Issue
Problem: In a traditional change detection scenario, picture a complex component hierarchy with nested components. Angular triggers a change detection cycle that goes through the entire component tree when a state change happens, such as a user clicking a button. This method can cause performance issues in large applications, especially with frequent state changes, as the detection process becomes more time-consuming with a greater number of components and deeper change origins.
With Signals: State changes using Signals are contained inside the Signal itself. Only the components that have specifically subscribed to a Signal are notified when its value changes.
Bundle Size
Problem: For detecting changes within the application, angular relies on zone.js, which is a third-party library.
With Signals: From Angular 18, you can configure applications, that can run without zone.js
Diminished boilerplate
A large amount of boilerplate code is frequently involved in managing state with observables and subjects, including handling asynchronous flows and subscriptions and unsubscriptions.
Signals provide a more compact and expressive API, which reduces this complexity.
Conclusion
Angular Signals provide a robust mechanism for handling data within your Angular applications. Take a thoughtful approach by evaluating these aspects to ascertain whether Signals align with the requirements of your particular use case.
Here’s a balanced perspective:
Embrace Signals when: You have frequently changing data, complex data flows, or require a more reactive approach. Their performance improvements and streamlined data management can significantly benefit your application.
Proceed with caution when: You’re dealing with simple data or are new to reactive programming. Consider the learning curve and potential testing challenges before diving headfirst into Signals.
In essence, Signals are a valuable addition to the Angular developer’s toolkit, but they should be used judiciously based on project needs and complexity
For your reference, I’ve shared a relevant
Git repository here: GitHub Repo
Live Demo: https://kashif-ali-khan.github.io/signal-project/home
If you want to play around with the code and see how it works: Stackblitz url
Reference: https://angular.io/guide/signals