Signals: O Novo Padrao de Reatividade Que Esta Dominando o JavaScript
Ola HaWkers, uma mudanca significativa esta acontecendo no ecossistema JavaScript em 2026. Signals, o primitivo de reatividade que nasceu no SolidJS, agora e o padrao adotado por Vue, Angular, Svelte e esta sendo proposto para inclusao no JavaScript nativo atraves do TC39.
Voce ja se perguntou por que tantos frameworks estao convergindo para o mesmo modelo de reatividade?
O Que Sao Signals
Entendendo o conceito fundamental.
Definicao Simples
Signals sao containers reativos para valores:
Caracteristicas principais:
- Armazenam um valor
- Notificam automaticamente quando mudam
- Permitem derivacoes (computed values)
- Sao mais granulares que estado tradicional
Analogia:
Pense em Signals como celulas de uma planilha. Quando voce muda uma celula, todas as formulas que dependem dela atualizam automaticamente.
Por Que Signals Importam
O problema que resolvem:
Reatividade tradicional (React):
- Re-renderiza componentes inteiros
- Precisa de memoization manual
- Virtual DOM para diff
- Overhead de memoria
Reatividade com Signals:
- Atualiza apenas o que mudou
- Reatividade automatica e granular
- Sem Virtual DOM necessario
- Performance superior
Como Signals Funcionam
A mecanica por tras da magia.
Anatomia de um Signal
Estrutura basica:
// Criando um signal simples
import { signal, computed, effect } from '@preact/signals-core';
// Signal basico - container reativo
const count = signal(0);
// Lendo o valor
console.log(count.value); // 0
// Modificando o valor
count.value = 1;
// Computed - valor derivado
const doubled = computed(() => count.value * 2);
console.log(doubled.value); // 2
// Effect - side effect reativo
effect(() => {
console.log(`Count is now: ${count.value}`);
});
// Quando count muda, o effect roda automaticamente
count.value = 5; // Loga: "Count is now: 5"O Grafo de Dependencias
Como os signals se conectam:
// Sistema de signals com dependencias
const firstName = signal('Maria');
const lastName = signal('Silva');
// Computed que depende de dois signals
const fullName = computed(() => {
return `${firstName.value} ${lastName.value}`;
});
// Computed que depende de outro computed
const greeting = computed(() => {
return `Ola, ${fullName.value}!`;
});
// Effect que observa o grafo completo
effect(() => {
document.title = greeting.value;
});
// Mudar qualquer signal propaga a mudanca
firstName.value = 'Ana';
// Automaticamente: fullName = "Ana Silva"
// Automaticamente: greeting = "Ola, Ana Silva!"
// Automaticamente: document.title atualizadoReatividade Granular
A diferenca crucial:
// Exemplo: Lista de tarefas com signals
const todos = signal([
{ id: 1, text: 'Estudar Signals', done: false },
{ id: 2, text: 'Criar projeto', done: false },
{ id: 3, text: 'Publicar artigo', done: true },
]);
// Computed para tarefas pendentes
const pendingCount = computed(() => {
return todos.value.filter(t => !t.done).length;
});
// Computed para tarefas completas
const completedCount = computed(() => {
return todos.value.filter(t => t.done).length;
});
// Funcao para marcar como feito
function toggleTodo(id) {
todos.value = todos.value.map(todo =>
todo.id === id
? { ...todo, done: !todo.done }
: todo
);
}
// Apenas os contadores que mudaram sao recalculados
toggleTodo(1);
// pendingCount: 2 -> 1 (recalculado)
// completedCount: 1 -> 2 (recalculado)
Signals nos Frameworks Modernos
Como cada framework implementa.
Vue 3 - Composition API
Vue usa Signals internamente:
// Vue 3 com Composition API (usa signals por baixo)
import { ref, computed, watchEffect } from 'vue';
export default {
setup() {
// ref() e um signal
const count = ref(0);
// computed() e um signal derivado
const doubled = computed(() => count.value * 2);
// watchEffect() e um effect
watchEffect(() => {
console.log(`Count: ${count.value}`);
});
function increment() {
count.value++;
}
return { count, doubled, increment };
}
};Angular 16+ - Signals Nativos
Angular adotou signals oficialmente:
// Angular com Signals (16+)
import { Component, signal, computed, effect } from '@angular/core';
@Component({
selector: 'app-counter',
template: `
<div>
<p>Count: {{ count() }}</p>
<p>Doubled: {{ doubled() }}</p>
<button (click)="increment()">+1</button>
</div>
`
})
export class CounterComponent {
// Signal com valor inicial
count = signal(0);
// Computed signal
doubled = computed(() => this.count() * 2);
constructor() {
// Effect para side effects
effect(() => {
console.log(`Count changed to: ${this.count()}`);
});
}
increment() {
// Duas formas de atualizar
this.count.set(this.count() + 1);
// ou
this.count.update(c => c + 1);
}
}SolidJS - O Pioneiro
Onde tudo comecou:
// SolidJS - Signals nativos desde o inicio
import { createSignal, createEffect, createMemo } from 'solid-js';
function Counter() {
// createSignal retorna [getter, setter]
const [count, setCount] = createSignal(0);
// createMemo e o computed do Solid
const doubled = createMemo(() => count() * 2);
// createEffect para side effects
createEffect(() => {
console.log(`Count is: ${count()}`);
});
return (
<div>
<p>Count: {count()}</p>
<p>Doubled: {doubled()}</p>
<button onClick={() => setCount(c => c + 1)}>
Increment
</button>
</div>
);
}
Proposta TC39 para JavaScript Nativo
Signals podem entrar na linguagem.
Status Atual
A proposta no TC39:
Situacao em 2026:
- Stage 1 aprovado
- Discussoes ativas para Stage 2
- Apoio de multiplos vendors
- Implementacao experimental em andamento
O que significa:
- Signals podem ser nativos do JavaScript
- Interoperabilidade entre frameworks
- Performance ainda melhor
- API padronizada
API Proposta
Como seria no JavaScript nativo:
// API proposta para JavaScript nativo (TC39)
// Criando um Signal nativo
const count = new Signal.State(0);
// Lendo valor
console.log(count.get()); // 0
// Modificando valor
count.set(1);
// Computed Signal
const doubled = new Signal.Computed(() => count.get() * 2);
// Watcher (similar ao effect)
const watcher = new Signal.subtle.Watcher(() => {
console.log('Dependencies changed!');
});
watcher.watch(count);
// Uso em frameworks seria simplificado
// Frameworks poderiam compartilhar signals entre siBeneficios da Padronizacao
Por que isso importa:
Para desenvolvedores:
- Uma API para aprender
- Signals funcionam igual em qualquer framework
- Menos lock-in de framework
- Migracoes mais faceis
Para o ecossistema:
- Bibliotecas universais de signals
- Melhor tooling e debugging
- Performance otimizada pelo engine
- Menos codigo de framework
Comparando Abordagens de Reatividade
Signals vs outras opcoes.
Signals vs useState (React)
Diferencas fundamentais:
| Aspecto | useState | Signals |
|---|---|---|
| Granularidade | Componente | Valor individual |
| Re-render | Componente inteiro | Apenas onde usado |
| Memoization | Manual (useMemo) | Automatica |
| Batching | Automatico | Automatico |
| Debuggability | DevTools | Grafo visivel |
Signals vs RxJS
Duas abordagens reativas:
// RxJS - Streams de eventos
import { BehaviorSubject, map } from 'rxjs';
const count$ = new BehaviorSubject(0);
const doubled$ = count$.pipe(map(x => x * 2));
doubled$.subscribe(value => console.log(value));
count$.next(1);
// Signals - Valores reativos
const count = signal(0);
const doubled = computed(() => count.value * 2);
effect(() => console.log(doubled.value));
count.value = 1;Quando usar cada um:
- RxJS: Eventos asincronos complexos, streams de dados
- Signals: Estado de UI, valores sincronos reativos
Padroes Avancados com Signals
Tecnicas profissionais.
Store Pattern
Organizando estado global:
// Store pattern com signals
import { signal, computed } from '@preact/signals-core';
function createStore() {
// Estado privado
const _user = signal(null);
const _cart = signal([]);
const _loading = signal(false);
// Computed publicos
const isLoggedIn = computed(() => _user.value !== null);
const cartTotal = computed(() =>
_cart.value.reduce((sum, item) => sum + item.price, 0)
);
const cartCount = computed(() => _cart.value.length);
// Actions
async function login(credentials) {
_loading.value = true;
try {
const user = await api.login(credentials);
_user.value = user;
} finally {
_loading.value = false;
}
}
function addToCart(product) {
_cart.value = [..._cart.value, product];
}
function removeFromCart(productId) {
_cart.value = _cart.value.filter(p => p.id !== productId);
}
return {
// Estado (readonly)
user: computed(() => _user.value),
cart: computed(() => _cart.value),
loading: computed(() => _loading.value),
// Computed
isLoggedIn,
cartTotal,
cartCount,
// Actions
login,
addToCart,
removeFromCart,
};
}
export const store = createStore();Signals com TypeScript
Tipagem forte:
// Signals com TypeScript completo
import { signal, computed, Signal, ReadonlySignal } from '@preact/signals-core';
interface User {
id: string;
name: string;
email: string;
}
interface Todo {
id: string;
text: string;
done: boolean;
}
// Signal tipado
const currentUser: Signal<User | null> = signal(null);
// Array de signals
const todos: Signal<Todo[]> = signal([]);
// Computed tipado
const pendingTodos: ReadonlySignal<Todo[]> = computed(() =>
todos.value.filter(t => !t.done)
);
// Funcao tipada que usa signals
function addTodo(text: string): void {
const newTodo: Todo = {
id: crypto.randomUUID(),
text,
done: false,
};
todos.value = [...todos.value, newTodo];
}
Performance: Signals vs Virtual DOM
Os numeros falam.
Benchmarks Comparativos
Testes reais de performance:
Cenario: Lista com 10.000 items, atualizacao de 1 item
| Framework | Tempo de Update | Memoria |
|---|---|---|
| React (VDOM) | 45ms | 12MB |
| Vue 3 (Signals) | 8ms | 6MB |
| Solid (Signals) | 3ms | 4MB |
| Svelte 5 (Signals) | 5ms | 5MB |
Por que signals sao mais rapidos:
- Sem diff de Virtual DOM
- Atualizacao direta no DOM
- Menos garbage collection
- Grafo de dependencias otimizado
Quando VDOM Ainda Faz Sentido
Nem sempre signals sao melhores:
VDOM funciona bem para:
- Componentes que mudam completamente
- Server-side rendering
- Ecossistema React existente
- Time já familiarizado
Signals brilham em:
- Atualizacoes granulares frequentes
- Aplicacoes data-intensive
- Dashboards em tempo real
- Mobile/baixa potencia
Migrando Para Signals
Guia pratico de adocao.
Estrategia Incremental
Passos recomendados:
- Aprenda os conceitos em projeto pequeno
- Experimente em componentes isolados
- Migre stores para signals primeiro
- Refatore componentes gradualmente
- Monitore performance antes/depois
Armadilhas Comuns
O que evitar:
// ERRADO: Desestruturar o valor perde reatividade
const { value } = count; // value nao e reativo!
// CERTO: Sempre acesse .value quando precisar
const currentCount = count.value; // reativo
// ERRADO: Mutar arrays/objetos diretamente
todos.value.push(newTodo); // Nao dispara update!
// CERTO: Criar nova referencia
todos.value = [...todos.value, newTodo]; // Dispara update
// ERRADO: Effects com dependencias nao rastreadas
effect(() => {
const id = someNonSignalVar; // Nao rastreado!
fetchData(id);
});
// CERTO: Use signals para todas as dependencias
const idSignal = signal(someId);
effect(() => {
fetchData(idSignal.value); // Rastreado corretamente
});A convergencia do ecossistema JavaScript para Signals representa uma maturidade da industria em reatividade frontend. Em 2026, entender Signals nao e mais opcional - e fundamental para qualquer desenvolvedor frontend moderno.
Se voce quer entender como essas mudancas afetam sua carreira, recomendo que de uma olhada em outro artigo: As Habilidades Que Todo Desenvolvedor Precisa Dominar em 2026 onde voce vai descobrir o que o mercado esta exigindo.
Bora pra cima! 🦅
🎯 Junte-se aos Desenvolvedores que Estao Evoluindo
Milhares de desenvolvedores ja usam nosso material para acelerar seus estudos e conquistar melhores posicoes no mercado.
Por que investir em conhecimento estruturado?
Aprender de forma organizada e com exemplos praticos faz toda diferenca na sua jornada como desenvolvedor.
Comece agora:
- 1x de R$9,90 no cartao
- ou R$9,90 a vista
"Material excelente para quem quer se aprofundar!" - Joao, Desenvolvedor

