TS Bus
A lightweight JavaScript/TypeScript event bus to help manage your application architecture.
The following examples are in TypeScript but you can use this in JavaScript as well.
Installation
Use your favourite npm client to install ts-bus. Types are included automatically.
Npm:
npm install ts-bus
Yarn:
yarn add ts-bus
Usage
Create your EventBus globally somewhere:
import { EventBus } from "ts-bus";
export const bus = new EventBus();
Next create some Events:
import { createEventCreator } from "ts-bus";
type FirstEvent = {
type: "FIRST_EVENT";
payload: {
id: string;
label: string;
};
};
export const firstEvent = createEventCreator<FirstEvent>("FIRST_EVENT");
export const otherEvent = createEventCreator<{
type: "OTHER_EVENT";
payload: { label:string }
};>("OTHER_EVENT");
Let's subscribe to our events
import { firstEvent, otherEvent } from "./event";
import { bus } from "./bus";
const unsubscribe = bus.subscribe(firstEvent, event => {
const { id, label } = event.payload;
doSomethingWithFirstEvent({ id, label });
});
setTimeout(unsubscribe, 20 * 1000);
Elsewhere publish your event
import { firstEvent, otherEvent } from "./events";
import { bus } from "./bus";
function handleButtonClick() {
bus.publish(firstEvent({ id: "my-id", label: "This is an event" }));
}
function handleButtonRightClick() {
bus.publish(otherEvent({ label: "You right clicked" }));
}
Usage with React
import React from "react";
import App from "./App";
import { EventBus } from "ts-bus";
import { BusProvider } from "ts-bus/react";
const bus = new EventBus();
export default () => (
<BusProvider value={bus}>
<App />
</BusProvider>
);
import { useBus } from "ts-bus/react";
import { kickoffSomeProcess } from "./my-events";
function ProcessButton(props) {
const bus = useBus();
const handleClick = React.useCallback(() => {
bus.publish(kickoffSomeProcess(props.data));
}, [bus]);
return <Button onClick={handleClick}>Go</Button>;
}
If you want to avoid the direct dependency you can use the event object:
bus.publish({ type: "KICKOFF_SOME_PROCESS", payload: props.data });
Alternative to Redux with useBusReducer
This can be used as a much more flexible alternative to Redux because not every event requires a corresponding state change. Also you can hook multiple frameworks together and create microfrontends with this technique.
import { useBusReducer } from "ts-bus/react";
function Main(props: Props) {
const state = useBusReducer(
produce((state, action) => {
switch (action.type) {
case "TASK_MOVED": {
return state;
}
case "TASK_CREATED": {
return state;
}
case "TASK_UPDATED": {
return state;
}
default:
return state;
}
}),
initState
);
return <MyApp state={state}>{children}</MyApp>;
}