If you've been responsible for large JavaScript applications in production, you've probably found yourself tangled in a web of RxJS callbacks before. Don't get us wrong: it's a great library for reactive programming, and one that we use for many of our clients. However, even when you follow best practices, keeping your change detection performant and your code readable can be a real challenge.
But what if there was a simpler, faster way to handle reactivity in your Angular projects? A way to write code that's both elegant and efficient? Well, as of Angular 17 (16 if you count Developer Preview), there is! Signals is a powerful new feature that streamlines how we manage change detection and build more performant applications. In this post, we'll explore what Signals does different, dive into real-world use cases (with code!), and look at what this means for the future of Angular development.
Signals offers a more direct and efficient approach to reactivity compared to traditional observables. Instead of relying on streams of data, Signals lets you define reactive values and directly observe changes. It basically gives you fine-grained control over your application's reactivity, with some significant advantages.
Let's move from theory to practice, starting with a minor disclaimer. We're already using Signals in several applications, but not every project can (or should) adopt Signals overnight. Some of our clients don't even allow it due to some advanced Signals still being in Developer Preview. With that out of the way, let's look at some ways in which we can use this new feature.
One area where Signals have made a real difference is in taming complex forms. As any Angular developer knows, managing user input in forms can quickly become a mess of values that depend on each other. It's all too easy to end up with code that's difficult to read and even harder to maintain.
Here's an example:
Signals offer a much cleaner solution. It lets us directly observe and react to changes in individual form fields, making it significantly easier to implement complex form logic in a way that's both performant and understandable.
Here's what that same RxJS code snippet looks like with the Signals functionality:
But that's not all – things can get even better. If you use effect(), you can use one of the computed signals (calculated based on user input) to send out API calls that retrieve additional information.
Without Signals, the RxJS code to achieve the same is more complex. Keep in mind that you'll also have to make sure that everything gets unsubscribed, or you'll risk causing memory leaks.
Component communication
Another area we're exploring is Signal-based component communication. While this is still in developer preview, it has the potential to be a game-changer. It makes passing data between parent and child components is as simple as setting a value.
Without Signals, you had to use ‘!’ as a definitive assignment assertion, telling TypeScript that a value would be assigned. You also had to wrestle with @Input and @Output:
What if you still need (or want) to use Observables?
Of course, we know that not every project can (or should) adopt Signals overnight. Many existing applications rely heavily on Observables, and refactoring everything at once simply isn't practical. That's where the beauty of Signals' interoperability with RxJS comes in.
The toSignal function provides a bridge between the two worlds. It lets us convert Observables to Signals, making migrations easier. In other words: we can start incorporating Signals into new features or specific parts of our applications without having to rewrite everything from scratch.
Here's an example to make things clear. On a service level, you can use Observables to retrieve data from the backend.
So, what does the future hold for Signals? We're excited to see how this new feature continues to evolve alongside Angular. There are a few interesting things on the horizon that we're keeping a close eye on.
For one, Angular might finally be ready to ditch Zone.js! It has been a core dependency for a long time, but let's just say it's not without its quirks (and performance overhead). We think that Signals are an important step towards a Zone-less Angular, potentially leading to even faster change detection and a smoother development experience.
We also expect the Angular team to continue improving and refining Signals themselves. As more developers start using them in real-world projects, new use cases and challenges will emerge. This will (hopefully) lead to more robust and feature-rich implementations in future Angular releases. Definitely something to look forward to!
Signals offer a great new way to manage reactivity in your Angular applications, bringing performance gains, code clarity, and a more intuitive developer experience. They're still pretty new, but they have the potential to fundamentally change how we build Angular applications, and we're excited to see what the future holds.
If you'd also like to work in an environment where you get to explore the latest technologies in everything related to Java and JavaScript, take a look at our Careers page!