How to use Angular Signals
Tags: angular, rxjs, typescript
Published: 2023-06-23 06:54:23

---
title: How to use Angular Signals
published: true
date: 2023-06-21 15:33:50 UTC
tags: angular, rxjs, typescript
canonical_url: https://byrayray.dev/posts/2023-06-21-how-to-use-angular-signals
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qrf51ent09wjys4k9brw.png
---

Angular Signals are hot right now! Even if you still need to start using them because you're not on Angular 16, Making your Angular development more straightforward and future-proof is worth your time.

Do you find RxJS complex? Well, you are not the only one. So many others think that way. Well, Angular Signals solves that problem for so many developers. So let's dive into it together.

![divider-byrayray.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1629890886208/NhHYvPmBA.png)

### Sources:

- [Github](https://github.com/devbyray/angular-signals-vs-rxjs)

- [CodeSandbox](https://codesandbox.io/p/github/devbyray/angular-signals-vs-rxjs/main?layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522panelType%2522%253A%2522TABS%2522%252C%2522id%2522%253A%2522clim5w3tu00753p6olf6t445f%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522panelType%2522%253A%2522TABS%2522%252C%2522id%2522%253A%2522clim5w3tu00763p6ok5kqy7xm%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%252C%2522sizes%2522%253A%255B65.34208440466293%252C34.65791559533707%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clim5w3tu00753p6olf6t445f%2522%253A%257B%2522id%2522%253A%2522clim5w3tu00753p6olf6t445f%2522%252C%2522tabs%2522%253A%255B%257B%2522type%2522%253A%2522FILE%2522%252C%2522filepath%2522%253A%2522%252Fsrc%252Fapp%252Fsignals-updates-array%252Fsignals-updates-array.component.ts%2522%252C%2522id%2522%253A%2522clj5ojqfc00ro3p6o339jgi5z%2522%252C%2522mode%2522%253A%2522permanent%2522%257D%255D%252C%2522activeTabId%2522%253A%2522clj5ojqfc00ro3p6o339jgi5z%2522%257D%252C%2522clim5w3tu00763p6ok5kqy7xm%2522%253A%257B%2522id%2522%253A%2522clim5w3tu00763p6ok5kqy7xm%2522%252C%2522tabs%2522%253A%255B%257B%2522type%2522%253A%2522TASK_LOG%2522%252C%2522taskId%2522%253A%2522start%2522%252C%2522id%2522%253A%2522clim5wjf200cy3p6o6ltrngnd%2522%252C%2522mode%2522%253A%2522permanent%2522%257D%252C%257B%2522type%2522%253A%2522TASK_PORT%2522%252C%2522taskId%2522%253A%2522start%2522%252C%2522port%2522%253A4200%252C%2522id%2522%253A%2522clim5wpod00i73p6obec6k6sr%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522path%2522%253A%2522%252F%2522%257D%255D%252C%2522activeTabId%2522%253A%2522clim5wpod00i73p6obec6k6sr%2522%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A29.677019335262912%257D)

- [Example website](https://angular-signals-vs-rxjs.vercel.app/)

![divider-byrayray.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1629890886208/NhHYvPmBA.png)

## Signals

Angular Signals are reactive properties in your Angular component, directive, or service. They update their value automatically; you don't need to listen to changes. No, they are doing all of that for you. Let's start with creating a Signal and showing it in the view.

### Get the value

Let's start simple. Getting a value from a signal is pretty straightforward.

If we want to show the value of a signal in the view, we need to define it first in the component.

```
@Component({...})
export class Component {
    count = signal<number>(0)
}

```

Then in the view, we can output it in an expression like this:

```
<div>{{ count() }}</div>

```

It is that easy. But how do we use a value of a signal in our component?

### How to get a value in a component class

The class of your component is also slightly different. The `Signal` value can be retrieved as easily as `this.count()`.

```
@Component({...})
export class Component {
    count = signal<number>(0)

    private logCount(): void {
        console.log('Count: ', this.count())
    }
}

```

Since signals are built for reactivity in Angular, we want to set and update a value in a signal. Let's dive into that.

![divider-byrayray.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1629890886208/NhHYvPmBA.png)

### Setting and updating the value

Reading the values of a `Signal` is simple. But if you are used to RxJS with Observables and Behavioursubjects, for example, this is a bit different, but I know you will love the simplicity!

By default, you can give a signal a value (just like the `BehaviourSubject`). When the value is changed, the view is updated automatically. Setting the value of a signal can be done with

```
@Component({...})
export class Component {
    count = signal<number>(0)

    private changeCount(): void {
        this.count.set(30)
    }
}

```

### How to update a value in a Signal based on the previous value

If you want to update your `Signal` based on the previous value, use the `update()` method.

```
count = signal(25)

// Update value
this.signal.update(prevValue => prevValue + 10) // 35

```

When the update has been done, it will automatically be reflected in the view.

![divider-byrayray.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1629890886208/NhHYvPmBA.png)

### How to update a signal with an array of objects

Updating an Array of Objects is equally simple with Signals. For this, we will use the `.mutate()` method.

Let's say we have an Array of Objects. Each Object has a price property. What if we want to update the first price, we can do that with `.mutate()` like this.

```
export class SignalsUpdatesArrayComponent {
    prices = signal<Obj[]>([
      { price: 10 }, 
      { price: 20 }, 
      { price: 30 }
    ])

    updatePrice(): void {
        this.prices.mutate(value => (value[0].price = this.getRandomPrice()))
    }

    getRandomPrice(): number {
        return Math.round(Math.random() * 100)
    }
}

```

We call the `updatePrice()` in the template, and it will be performed.

But what if we want to add an Object to the Array on the fly? Well just as easy. Push a new Object in the `mutate()` method.

```
export class SignalsUpdatesArrayComponent {
    prices = signal<Obj[]>([
      { price: 10 }, 
      { price: 20 }, 
      { price: 30 }
    ])

    updatePrice(index: number): void {
        this.prices.mutate(value => (value[index].price = this.getRandomPrice()))
    }
    addPrice(): void {
        this.prices.mutate(value => value.push({ price: this.getRandomPrice() }))
    }

    getRandomPrice(): number {
        return Math.round(Math.random() * 100)
    }
}

```

[I created an example](https://angular-signals-vs-rxjs.vercel.app/) so you can see that it works by easily updating the Array.

![divider-byrayray.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1629890886208/NhHYvPmBA.png)

> If you want to learn more about [RxJS Subjects, BehaviourSubjects and more](https://byrayray.dev/posts/2021-09-03_when-to-use-rxjs-subject-behavioursubject-replaysubject-asyncsubject-or-void-subject-in-angular-c2e9db61b4a0)? Then read the post I wrote about that in detail.

![divider-byrayray.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1629890886208/NhHYvPmBA.png)

## Effect

### Listen to value updates with effect()

Listening to changes can easily be done with `effect()` . But it's not equal to the behavior of listening to changes of an `Observable` or `BehaviourSubject` in RxJS. So let's see what the difference is.

The `effect()` method with Signals is mostly for updating logging, saving data to local storage, or updating your canvas. By default, you are not allowed to update a signal within the `effect()`.

For example, we create a component where we want to log when the price is updated. In the constructor, we have added the `effect()` to show that the price has been updated. In the HTML, we create a button to update the price.

```
@Component({...})
export class SignalsGetUpdatesComponent {
  price = signal<number>(10);
  priceUpdated = signal<boolean>(false);

  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);
  }
}


<div>
    <h2>Get updates</h2>
    <p>
        Add {{30 | currency: 'EUR'}} to the price <br />
        of {{10 | currency: 'EUR'}} and notify.
    </p>

    <p><strong>Is price updated: </strong> {{priceUpdated() ? "👍" : "👎"}}</p>
    <p><strong>Price: </strong> {{price() | currency:'EUR'}}</p>
    <button (click)="updatePrice()" [ngClass]="{'is-updated': priceUpdated()}">Add {{30 | currency: 'EUR'}}</button>
</div>

```

In this case, I update the `priceUpdated` signal in the `updatePrice()` method while updating the price. When you use RxJS with a `BehaviourSubject`, you could have done that in the `subscribe()` method. This is a matter of taste on what you prefer.

If you know what you do and are aware of creating possibly an infinite loop with updating signals in the `effect(),` you can do that by passing a second parameter `{ allowSignalWrites: true }`.

```
@Component({...})
export class SignalsGetUpdatesEffectUpdateComponent {
    price = signal<number>(10)
    priceUpdated = signal<boolean>(false)

    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)
    }
}


<div>
    <h2>Get updates and overwrite signal in effect</h2>
    <p>
        Add {{30 | currency: 'EUR'}} to the price <br />
        of {{10 | currency: 'EUR'}} and notify.
    </p>

    <p><strong>Is price updated: </strong> {{priceUpdated() ? "👍" : "👎"}}</p>
    <p><strong>Price: </strong> {{price() | currency:'EUR'}}</p>
    <button (click)="updatePrice()" [ngClass]="{'is-updated': priceUpdated()}">Add {{30 | currency: 'EUR'}}</button>
</div>

```

The effect will run when the component is initialized, like the `ngOnInit`.

![divider-byrayray.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1629890886208/NhHYvPmBA.png)

## Computations

Let's talk about computations. You use a computation when calculating or doing string concatenation based on changing one or more values.

### Get the value from the computation

```
// Signal
getDoubleCount() {
    console.log(this.doubleCount())
}

// BehaviourSubject
getDoubleCount() {
    this.doubleCount.subscribe((value) => console.log(value))
}

```

And this is where getting the simplest thing, as getting the double-count value, is going to be less straightforward with the `BehaviourSubject` if you compare it with the `Signal`.

Because with the `BehaviourSubject`, you want to ensure the subscription is removed when it's not needed anymore.

With signals, Angular handles many things for you, more than using RxJS. With RxJS, we can often get buried in complex and hard-to-read code, especially for people who have yet to get used to Angular or RxJS.

For example, with RxJS, we need to clean our subscriptions ourselves; with signals, we don't have that because Angular handles that for us.

```
// Inside a component class
// ...
destroy$ = new Subject<void>();

ngOnDestroy() {
    this.destroy$.next();
}

getDoubleCount() {
    this.doubleCount
        .pipe(takeUntil(this.destroy$))
        .subscribe((value) => console.log(value))
}
//...

```

No, signals bring a lot of simplicity while using reactivity. Developers coming from Vue will be used to a very similar way of handling reactive properties.

For example, let's update a first name and show the user the full name. We will use `computed()` to help us with that.

```
@Component({...})
export class SignalsComputeValueComponent {
  firstName = signal('Bart')
  lastName = signal('The Great')

  fullName = computed(() => this.firstName() + ' ' + this.lastName())

  changeFirstName() {
    this.firstName.set('Ray')
  }
}


<div>
    <h2>Get updates and overwrite signal in effect</h2>

    <p>
        <strong>Firstname:</strong> {{ firstName() }} <br />
        <strong>Lastname:</strong> {{ lastName() }}
    </p>
    <p><strong>Fullname computation:</strong> {{ fullName() }}</p>

    <p>
        <button (click)="changeFirstName()">Update firstname</button>
    </p>
</div>

```

As you can see, the `fullName` property merges two strings in the `computed()` method. When the `firstName` is updated, the `fullName` will be updated automatically, and you can see it directly in the view. It is that simple!

![divider-byrayray.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1629890886208/NhHYvPmBA.png)

## Thanks

Now you are entirely up to date with how to use Angular Signals. I hope you can start using them right away.

![](https://devbyrayray.hashnode.dev/images/0__4aTcitCaVTWHHeiO.jpg)

![hashnode-footer.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1629789655319/nBF6anHH4w.png)

_After reading this story, I hope you learned something new or are inspired to create something new! 🤗 If I left you with questions or something to say as a response, scroll down and type me a message, send me a_ [_DM on Twitter @DevByRayRay_](https://twitter.com/@devbyrayray)

_Want to receive new posts in your mailbox? No, not only a link, just the whole article without any ads_ 🤗 _or other stuff._ [**_Then subscribe to my newsletter_**](https://byrayraydev.substack.com/) _👍. I promise I wont spam you, only the most important and best-quality content will be sent to you ._

> Did you know that you can create a [Developer blog like this one, yourself](https://hashnode.com/@devbyrayray/joinme)? It's entirely for free. 👍💰🎉🥳🔥