Procurando por técnicas de programção?

Event Bus (Cópia)

How to use Events with TypeScript and React

Trabalhando com Eventos em Aplicações Frontend

Eventos são uma forma elegante e desacoplada de comunicar diferentes partes de uma aplicação. Neste artigo, vamos entender o que são eventos, por que usá-los, quando aplicar e como implementar um sistema de eventos simples e eficaz em JavaScript/TypeScript.

O que são eventos?

Eventos são notificações que um módulo dispara para avisar que algo aconteceu. Outros módulos, que estejam "ouvindo" esse evento, podem reagir a ele. Essa abordagem é baseada no padrão de design Observer e permite desacoplar produtores e consumidores de ações.
No contexto do frontend, eventos são muito usados para:
  • Notificar contextos ou componentes de mudanças globais
  • Reagir a ações do usuário (login, logout, troca de idioma)
  • Comunicar diferentes partes da aplicação sem criar dependências diretas

Por que usar eventos?

Usar eventos permite:
  • Desacoplamento entre módulos e contexts
  • Reutilização de lógica sem duplicação
  • Facilidade de teste e isolamento de funcionalidades
  • Maior controle sobre fluxos de ações assíncronas
Exemplo clássico: vários módulos precisam reagir ao login do usuário. Com eventos, você dispara apenas um emit("login", data) e cada parte do sistema reage como necessário.

Quando usar eventos?

Eventos são ideais quando:
  • Você tem múltiplos contexts ou hooks que precisam reagir à mesma ação
  • A ordem dos providers React não é garantida (e isso impede comunicação direta)
  • Você precisa de baixo acoplamento entre partes do app
  • Eventos acontecem em nível global (ex: login/logout, mudança de ambiente, alteração de idioma)
Evite eventos para fluxos locais e simples — nesses casos, state e props ainda são a melhor abordagem.

Como usar eventos

A seguir, um exemplo de um globalEventBus simples em TypeScript, com suporte a múltiplos eventos e identificação de quem está inscrito:
type EventTypes = "login" | "logout" | "envChange";

type EventCallback<T = any> = (payload: T) => void;

type SubscriberEntry<T = any> = {
name: string;
callback: EventCallback<T>;
};

const subscribers: Record<EventTypes, SubscriberEntry[]> = {
login: [],
logout: [],
envChange: [],
};

export const subscribe = <T = any>(
event: EventTypes,
name: string,
cb: EventCallback<T>
) => {
subscribers[event].push({ name, callback: cb });
};

export const unsubscribe = <T = any>(
event: EventTypes,
name: string
) => {
subscribers[event] = subscribers[event].filter(s => s.name !== name);
};

export const emit = <T = any>(
event: EventTypes,
payload: T
) => {
console.log(`[EventBus] Emitting "${event}" to:`, subscribers[event].map(s => s.name));
subscribers[event].forEach(s => s.callback(payload));
};

Casos de uso prático

Nesse exemplo vamos configurar, disparar e escutar um evento de login


//src/globalEventBus.ts


type EventTypes = "login";


type EventCallback<T = any> = (payload: T) => void;


type SubscriberEntry<T = any> = {
name: string;
callback: EventCallback<T>;
};


const subscribers: Record<EventTypes, SubscriberEntry[]> = {
login: [],
};


export const subscribe = <T = any>(
event: EventTypes,
name: string,
cb: EventCallback<T>
) => {
subscribers[event].push({ name, callback: cb });
};


export const unsubscribe = <T = any>(
event: EventTypes,
name: string
) => {
subscribers[event] = subscribers[event].filter(s => s.name !== name);
};


export const emit = <T = any>(
event: EventTypes,
payload: T
) => {
console.log(`[EventBus] Emitting "${event}" to:`, subscribers[event].map(s => s.name));
subscribers[event].forEach(s => s.callback(payload));
};

emit("login", { userId: 42, enterpriseUuid: "abc", environmentUuid: "xyz" });
useEffect(() => {
subscribe("login", "EnvironmentContext", ({ environmentUuid }) => {
fetchAndSetEnvironment(environmentUuid);
});

return () => unsubscribe("login", "EnvironmentContext");
}, []);