npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@skarlatov/react-event-bus

v2.1.2

Published

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

Downloads

437

Readme

React Event Bus :zap:

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 :pizza:

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

Usage outside React components

The event bus can be accessed outside React components by using the setGlobalEventBusRef utility function and the contextCreated prop of the provider.

import { uniqueId } from "lodash";
import { EventBusProvider, setGlobalEventBusRef } from "@skarlatov/react-event-bus";

export function App() {
  return (
    <EventBusProvider 
      contextCreated={setGlobalEventBusRef}
      createUniqueId={uniqueId}>
      {/* The rest of your root app code is here */}
    </EventBusProvider>
  );
}

The global reference can be used to raise events from anywhere including stores and actions with the raiseEvent utility function. This function is safe in the sense that if the global ref is not initialized yet your app will not crash. Just the event won't be raised and a warning will be printed in the console.

For the sake of the example we update our PizzaEvents contract with a new 'pizza-ready' event.

export interface PizzaEvents {
  "pizza-ordered"?: (pizzaName: string) => void;
  // The new event
  "pizza-ready"?: (pizzaName: string) => void;
}

Now we can raise the event without the useEventBus hook like so:

import { useCallback } from 'react';
import { globalEventBus } from "@skarlatov/react-event-bus";
import { PizzaEvents } from "./contracts";

const { raiseEvent } = globalEventBus<PizzaEvents>();

export function PizzeriaKitchen() {
  const onPizzaReady = useCallback((name: string) => {
    raiseEvent("pizza-ready", name);
  }, []);

  return (
    <div>
      Pizzeria Kitchen
      <button onClick={() => onPizzaReady("New York")}>Pizza ready!</button>
    </div>
  );
}