JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 228
  • Score
    100M100P100Q77443F
  • License MIT

A simple implementation of the event bus pattern for React and React Native apps.

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 ⚡ drawing

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 🍕

1. 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>
  );
}

2. Events contract

export interface PizzaEvents {
  "pizza-ordered": (pizzaName: string) => void;
}

3. 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>
  );
}

4. Event consumer

import React, { useCallback, useMemo } 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);

  return (
    <div>
      Pizzeria Kitchen
    </div>
  );
}