Коли варто використовувати signal в Angular?

pic

Фото: craig kerwien на Unsplash

В останні роки фреймворк Angular зазнав значних змін у внутрішній архітектурі та механізмі виявлення змін. Якщо ви повертаєтеся до Angular після тривалої перерви, то будете здивовані змінами в самому фреймворку. Зокрема, Signal має замінити старий механізм виявлення змін, який використовувався раніше. Angular поступово відмовляється від використання zone.js для виявлення змін.

Що таке Signal коротко? Згідно з пропозицією t39
Декларативна модель програмування для оновлення на основі змін стану.

Так, t39 вже був запропонований для того, щоб зробити його стандартною веб-моделлю. Уже більшість фреймворків починають використовувати signals, таких як Angular, Ember, Preact, Qwik, RxJS, Solid, Svelte, Vue, Wiz тощо…

Чому Angular Signal?

Реалізація signal в Angular принесе величезні переваги, такі як:

Тонко налаштована реактивність: Перерендерюються тільки ті частини інтерфейсу, які залежать від сигналу.

Відстеження залежностей — значення сигналу можна отримати, викликавши його функцію-отримувач, що дозволяє Angular відстежувати, де використовується цей сигнал.

Мемоізація — обчислені функції Angular є чистими функціями, тому вони автоматично підтримують мемоізацію.

Ледаче обчислення — обчислені функції не будуть виконуватись, поки ви вперше не прочитаєте їх у компоненті/шаблоні.

Покращена продуктивність: Зменшує кількість зайвих циклів виявлення змін.

Типи сигналів

У наведеному прикладі ми використаємо 3 типи сигналів, розглянемо їх по черзі.

import { Component, signal, computed, effect } from '@angular/core';  

@Component({  
 selector: 'app-counter',  
 template: `  

Counter: {{ count() }}
Double Count: {{ doubleCount() }}
Increment    Decrement    
    `,   })   export class CounterComponent {    // Сигнал для збереження значення лічильника    count = signal(0);       // Обчислений сигнал для подвійного значення лічильника    doubleCount = computed(() => this.count() * 2);       constructor() {    // Ефект для логування змін лічильника    effect(() => {    console.log(`Count updated: ${this.count()}`);    });    }       // Методи для зміни значення лічильника    increment() {    this.count.set(this.count() + 1);    }       decrement() {    this.count.set(this.count() - 1);    }   } ``` 

**1) Записувані сигнали / Тільки для читання сигнали**  
Записуваний сигнал надає API для оновлення значень, сигнал для читання є постійною величиною, яку не можна змінити. Його можна використовувати в обчисленнях/ефектах. Змінна _count_ є записуваним сигналом.
 - Виконує роль реактивної змінної для збереження значення лічильника.
 - Отримує поточне значення через `this.count()`.
 - Оновлює значення через `this.count.set(newValue)`.

**2) Обчислені сигнали**  
Обчислені сигнали є лише для читання і виводять свої значення з інших сигналів. Змінна _doubleCount_ є обчисленим сигналом.  
 - Автоматично перераховує значення при зміні `count`.
 - Забезпечує синхронізацію похідних значень без необхідності ручного оновлення.

**3) Ефекти** _(ще на стадії попереднього перегляду в Angular 19)_  
Ефекти виконуються асинхронно під час процесу виявлення змін. Ефекти виконуються щоразу, коли сигнал або обчислене значення змінюється чи зчитується. Це зручно для налагодження.  
Спостерігає за змінами в `count` і виконує побічні ефекти, такі як логування.

## **Висновок**

Сподіваюся, що цей блог дасть корисні уявлення про signals. Підсумовуючи, слід використовувати signals у таких випадках:
 - Управління малими, реактивними фрагментами стану.
 - Оптимізація продуктивності важливих оновлень інтерфейсу.
 - Спрощення обчислень похідного стану та обробки побічних ефектів.

Якщо ви хочете дізнатися більше про те, як реалізовані signals в Angular, відвідайте ці посилання. Творець Solid [Ryan Carniato](https://www.youtube.com/@ryansolid) та учасник команди Angular обговорюють signal.



Перекладено з: [When to use angular Signal?](https://medium.com/@dinesh_here/when-to-use-angular-signal-77b27862d390)

Leave a Reply

Your email address will not be published. Required fields are marked *