Angular Signals: Guia Prático de Reatividade Moderna
Como usar Angular Signals para gerenciar estado reativo de forma simples e performática, substituindo BehaviorSubjects e reduzindo complexidade.
O Problema com RxJS para Estado Local
RxJS é poderoso para streams assíncronas, mas para estado simples de componentes, BehaviorSubjects adicionam complexidade desnecessária: gerenciar subscriptions, evitar memory leaks, operadores verbosos para transformações simples. Signals resolvem isso.
Signals Básicos
import { signal, computed, effect } from '@angular/core';
// Signal de escrita
const count = signal(0);
// Ler valor
console.log(count()); // 0
// Atualizar
count.set(5);
count.update(v => v + 1);
Computed Signals
Derivar valores reativamente sem subscription manual:
const firstName = signal('Ivan');
const lastName = signal('Reis');
const fullName = computed(() => `${firstName()} ${lastName()}`);
// Recalcula automaticamente quando firstName ou lastName mudam
console.log(fullName()); // 'Ivan Reis'
Effect para Side Effects
effect(() => {
console.log(`Usuário mudou para: ${fullName()}`);
// Executa automaticamente quando qualquer signal dependente muda
});
Signals em Componentes
@Component({
selector: 'app-counter',
template: `
<p>Contagem: {{ count() }}</p>
<button (click)="increment()">+1</button>
<p>Dobro: {{ double() }}</p>
`,
})
export class Counter {
readonly count = signal(0);
readonly double = computed(() => this.count() * 2);
increment() {
this.count.update(v => v + 1);
}
}
Signal Inputs (Angular 17.1+)
@Component({
selector: 'app-user-card',
template: `<h3>{{ displayName() }}</h3>`,
})
export class UserCard {
name = input.required<string>();
role = input<string>('user');
displayName = computed(() =>
`${this.name()} (${this.role()})`
);
}
Migrando de BehaviorSubject
// ANTES (RxJS)
private userSubject = new BehaviorSubject<User | null>(null);
user$ = this.userSubject.asObservable();
setUser(user: User) { this.userSubject.next(user); }
// DEPOIS (Signals)
private readonly _user = signal<User | null>(null);
readonly user = this._user.asReadonly();
setUser(user: User) { this._user.set(user); }
Quando Usar Cada Um
- Signals: estado local/global, dados síncronos, propriedades de UI, formulários
- RxJS: HTTP requests, WebSockets, eventos complexos com debounce/merge/switch, streams de dados
- Ambos:
toSignal()etoObservable()conectam os dois mundos



