JSPM

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

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

Package Exports

    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

    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>
      );
    }
    1. Define events contract
    export interface PizzaEvents {
      "pizza-ordered": (pizzaName: string) => void;
    }
    1. 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>
      );
    }
    1. 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>
      );
    }