Package Exports
- @skarlatov/react-event-bus
- @skarlatov/react-event-bus/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@skarlatov/react-event-bus) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
React Event Bus
Description
This package is an implementation of the event pattern. It allows direct, decoupled communication between entities (components, stores, actions etc.) in React or React Native applications.
Motivation
Using events makes it easier for components to react to changes without indirectly using central state or props with useEffect. This is a very common source of performance issues and other bugs in React apps.
Drawbacks
Relying too heavily on events for state management can result in code that is hard to follow especially in pure Javascript projects. Also beware of event storms (unintended cascade of events or infinite event loops).
Installation
Using npm
npm i @skarlatov/react-event-bus
Using yarn
yarn add @skarlatov/react-event-bus
Basic usage
- Context setup
import { uniqueId } from "lodash";
import { EventBusProvider } from "@skarlatov/react-event-bus";
export function App() {
/*
The provider needs a function that creates unique ids to keep
track of its subscriptions internally. The function is passed
as a prop so that the event bus library doesn't have any other
dependencies except React.
*/
return (
<EventBusProvider createUniqueId={uniqueId}>
{/* The rest of your root app code is here */}
</EventBusProvider>
);
}
- Define events contract
export interface PizzaEvents {
"pizza-ordered": (pizzaName: string) => void;
}
- Event emitter
import React, { useCallback } from "react";
import { useEventBus } from "@skarlatov/react-event-bus";
import { PizzaEvents } from "./contracts";
export function PizzeriaWaiter() {
const { raiseEvent } = useEventBus<PizzaEvents>()
const onOrderPizza = useCallback(() => {
raiseEvent("pizza-ordered", "New York");
}, [raiseEvent]);
return (
<div>
<div>Pizzeria Waiter</div>
<button onClick={onOrderPizza}>Order pizza!</button>
</div>
);
}
- Event consumer
import React, { useCallback } from "react";
import { useEventBus } from "@skarlatov/react-event-bus";
import { PizzaEvents } from "./contracts";
export function PizzeriaKitchen() {
const onPizzaOrdered = useCallback((name: string) => {
console.log(`We have a new pizza ${name} to make! Chop chop!`)
}, []);
// It is very important that the eventSubscriptions object
// has a stable reference. Otherwise the event bus will
// subscribe and unsubscribe from the event on every render.
const eventSubscriptions: PizzaEvents = useMemo(() => ({
"pizza-ordered": onPizzaOrdered,
}), [onPizzaOrdered]);
useEventBus<PizzaEvents>(eventSubscriptions);
const onOrderPizza = useCallback(() => {
raiseEvent("pizza-ordered", "New York");
}, [raiseEvent]);
return (
<div>
Pizzeria Kitchen
</div>
);
}