Learn Angular Signals - The Future of State Management
Learn Angular Signals - The Future of State Management

In this post you will learn what are Angular Signals and how we can use that in the nearest future.

So what are signals inside Angular? This is a new way of writing your code. Previously we wrote either just variables inside components or we had streams with RxJS.

Why do we need signals?

The first question here is why do we need signals at all. For this I must tell you some theory. In Angular we have such thing which is called Angular digest cycle.

If some change happens Angular doesn't know what changes. It simply checks every single component for the changes.

As you can understand this is really magical process because you don't need to do anything and everything just rerenders when needed. But when you have lots of components and lots of properties to check Angular becomes really slow.

This is why we have things like OnPush change detection which is not really a fix but more like a hack which helps that Angular checks less.

But now we have something new which is called Angular Signals.

Diagram

As you can see on the diagram signals are working completely different. You have a signal and consumers of this signal which are notified directly when you change the value.

With Signals Angular doesn't need to traverse the whole tree in order to check if we did some changes.

This must bring our applications on the next level.

Using signals

This brings us to the code. In Angular 15 signals are not available yet. Only from Angular 16 you can use them. If you want to test signals just use Angular 16 Next which is already available.

title = signal('')

This is how we create a single inside component. Now let's create an input and bind our title signal to it.

<input type="text" [value]="title()" (keyup)="changeTitle($event)" />
{{ title() }}

As you can see we used title signal in html with round brackets. So we called it as a function and this is a way to read value from the signal.

changeTitle(event: Event) {
  const title = (event.target as HTMLInputElement).value;

  this.title.set(title);
}

Here we implemented changeTitle method which updates our signal. As you can see we use .set to fully override a value in the signal.

Working signal

Now let's create a signal for array of users.

interface UserInterface {
  id: string;
  name: string;
}

export class AppComponent implements OnInit {
  title = signal('');
  users = signal<UserInterface[]>([]);

  ngOnInit(): void {
    setTimeout(() => {
      this.users.set([{ id: '1', name: 'Foo' }]);
    }, 2000);
  }
}

Here we created an interface for the user. We also defined our users signal with correct interface. Inside ngOnInit we set a value with setTimeout to simulate an API call.

Ways to update a signal

You already know how to fully override the value of the signal by using .set. But we have 2 more possibilities.

this.users.update((prevUsers) => [
  ...prevUsers,
  { id: '1', name: 'Foo' },
]);

Here we used .update instead which gives us access to the previous value in the signal. This is why we can use it in order to create a new value and return it.

this.users.mutate((currUsers) =>
  currUsers.push({ id: '1', name: 'Foo' })
);

It is also possible to use .mutate function where we get access to the current value in the signal and can mutate it. I personally don't like mutations this is why set and update look cleaner for me.

Effects in signals

One more thing that you must know about signals is that we have there effects. If you are familiar with React we have there such thing which is called useEffect. Which means we are triggering something after value changed.

titleChangeEffect = effect(() => {
  console.log('titleChangeEffect', this.title());
});

Here we defined an effect which is triggered after every signal change and we can do different side effects inside.

Computed

The last thing that you need to know in Angular signals is computed. It allows us to create new signals based on existing ones.

 usersTotal = computed(() => this.users().length);

Here we defined a signal usersTotal which will be changed every time when our users signal changes. It is extremely efficient and scalable. Now we can render it in html just like other signals.

My thoughts

Now you know how you can use signals. The last thing that I want to do is to change my feelings about signals and compare them to RxJS.

I understand that signals is much easier for people to get started that RxJS for example. This is true, you can master signals in 10 minutes. But you can't really do that with RxJS because there is lots of methods to learn and a lot of different combinations of them.

Essentially RxJS is a super powerful tool but it is not suitable for beginners. The main problem that I see is that Angular uses RxJS a lot. Now we are getting something new and the question is how we will use together Angular, Signals, RxJS and if RxJS will be still valid at all. Or we will just throw RxJS away and stick with the signals.

And actually if you want to learn Angular with NgRx from empty folder to a fully functional production application make sure to check my Angular and NgRx - Building Real Project From Scratch course.

📚 Source code of what we've done