Introdução
O Angular passou por uma grande evolução com a introdução dos Signals na versão 16 (estável a partir da v17). Essa nova primitiva de reatividade muda fundamentalmente como gerenciamos e propagamos estado na aplicação.
Se você quer entender as tendências modernas do framework, dominar Signals é essencial.
Objetivos de aprendizagem
- Distinguir signal, computed e effect.
- Modelar estado derivado sem duplicar valores.
- Escolher entre Signals e RxJS de acordo com o fluxo de dados.
O que é um Signal?
Em termos práticos, um Signal:
- Armazena um valor (qualquer tipo)
- Notifica automaticamente quem depende dele quando muda
- Rastreia dependências de forma transparente (sem necessidade de
subscribe)
import { signal, computed, effect } from "@angular/core";
// Criando um signal
const count = signal(0);
// Lendo o valor
console.log(count()); // 0
// Atualizando o valor
count.set(1);
count.update((v) => v + 1);Tipos de Signals
signal() — Signal mutável
O Signal básico. Você cria, lê e modifica seu valor diretamente.
const name = signal("André");
name.set("André Leite"); // substitui
name.update((prev) => prev.toUpperCase()); // transformacomputed() — Signal derivado
Deriva um valor a partir de outros Signals. Read-only e recalculado apenas quando as dependências mudam.
const firstName = signal("André");
const lastName = signal("Carvalho");
const fullName = computed(() => `${firstName()} ${lastName()}`);
// fullName() → "André Carvalho"effect() — Efeito colateral reativo
Executa um efeito quando qualquer Signal lido por ele muda. É apropriado para sincronizar APIs não reativas, como logging ou acesso imperativo ao DOM.
effect(() => {
console.log("Nome mudou para:", name());
});Signals vs RxJS
Entenda as diferenças:
| Aspecto | Signals | RxJS |
|---|---|---|
| Modelo | Push síncrono | Push assíncrono |
| API | Simples (signal, computed, effect) | Rico (Observable, operadores) |
| Curva de aprendizado | Baixa | Alta |
| Operações assíncronas | Limitado | Poderoso |
| Integração Angular | Nativa (v16+) | Histórica |
| Tree-shaking | Excelente | Depende do uso |
import { toSignal } from "@angular/core/rxjs-interop";
import { HttpClient } from "@angular/common/http";
// Convertendo Observable → Signal
const users = toSignal(this.http.get<User[]>("/api/users"), { initialValue: [] });Uso em Componentes
Substituindo @Input() com Signal Inputs (v17.1+)
import { Component, input, output } from "@angular/core";
@Component({ selector: "app-counter", template: `...` })
export class CounterComponent {
// Signal Input — read-only Signal derivado do pai
count = input<number>(0);
// Signal Output — equivalente ao EventEmitter
increment = output<void>();
}Modelando um formulário com Signal Forms
import { Component, signal } from "@angular/core";
import { form, FormField } from "@angular/forms/signals";
@Component({
imports: [FormField],
template: `
<input [formField]="profileForm.name" />
<p>Olá, {{ profileForm.name().value() }}!</p>
`,
})
export class FormComponent {
readonly profileModel = signal({ name: "" });
readonly profileForm = form(this.profileModel);
}form() cria uma árvore tipada a partir do model Signal, e [formField] sincroniza valor e estado do campo com a interface.
Vantagens dos Signals
- Reatividade granular — Apenas os componentes que dependem do Signal são re-renderizados
- Sem subscriptions — Não há risco de memory leak por esquecer de
unsubscribe - Debugging simples — O valor é síncrono e sempre acessível
- Bundle menor — Menor overhead que observables para casos simples
- Integração com o compilador — O Angular pode otimizar a detecção de mudanças
Casos de Uso
Perguntas técnicas
O que é um Signal no Angular e qual problema ele resolve?
Qual a diferença entre signal(), computed() e effect()?
Como Signals se integram com RxJS no Angular?
O que é Zone.js e como Signals mudam sua relação com o Angular?
Verifique seu entendimento
Qual ferramenta é mais adequada para representar um valor síncrono usado diretamente no template?
Conclusão
Signals oferecem reatividade síncrona e granular, enquanto RxJS permanece adequado a fluxos assíncronos e operadores complexos. As duas abordagens podem ser combinadas conforme o contexto.
Verifique seu entendimento
Qual primitiva deve representar um valor derivado de outros Signals?
Resposta: computed. computed deriva o valor declarativamente e acompanha apenas as dependências lidas durante o cálculo.
Revisão do artigo
Pontos principais
- — Signals armazenam e notificam mudanças de estado síncrono.
- — computed representa estado derivado e evita sincronização manual.
- — RxJS continua adequado a fluxos assíncronos e composição de eventos.