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

react-pusu

v2.1.0

Published

Simple pub-sub implementation APIs for React Components

Downloads

58

Readme

react-pusu

Simple pub-sub implementation APIs, HOCs & Hooks for React Components.

Pub-Sub implementation is one of the effective ways and most useful when the components, which are rendered across the page, even under different component hierarchies, need to communicate with each other. A simple example can be, a data refresh button placed in the header of the application. On click of this button the page should reload the data from server. There can be multiple pages which may need this type of functionality. Also, there can be multiple sections on a page which need to reload the data using their own API calls (may be using redux). So all these pages & components can actually subscribe to the refresh publication event. The refresh button can, on click, publish the event. And then all the subscribers can reload the data (may be using redux) from server by calling their own apis.

Compatibility

| React Version | react-pusu Compatibility | |--|--| | >= [email protected] | ^2.0.0 | | React@15, <= [email protected] | ^1.0.0 |

How to install

yarn add pusu react-pusu

npm install --save pusu react-pusu

createPublication<T>([name])

Parameters:

  • name: (Optional) String - Publication name. Useful in debugging.

Return value: Object - New publication

Creates & returns a unique new publication object.

Publication object is a simple javascript object { subscribers: [] } which has an array named subscribers. The array subscribers actually holds the references to the subscriber functions. Result is, all the subscribers (i.e. functions) of the publication are mapped inside the publication object itself. Whenever a publiser publishes any data for a publication then all the subscribers inside the publication are called with this data.

TypeScript

// refresh-page-data-publication.ts

import { createPublication } from 'pusu';

export default createPublication<{ asOfDate: Date }>('Refresh page data');

JavaScript

// refresh-page-data-publication.js

import { createPublication } from 'pusu';

export default createPublication('Refresh page Data');

Unique publication every time

Creation of a publication makes sure that each publication is unique in itself and removes the need of maintaining a unique key for each publication.

Even if multiple publications created with same name, then each publication will be treated as a separate publication without any conflicts.

Below code creates two separate unique publications publication1 & publication2 even though the publication names are same. Name is just for the sake of naming the publication so that its useful during debugging any issues.

TypeScript

import { createPublication } from 'pusu';

const publication1 = createPublication<{ asOfDate: Date }>('Refresh page data');
const publication2 = createPublication<{ asOfDate: Date }>('Refresh page data');

console.log(publication1 === publication2); //false

JavaScript

import { createPublication } from 'pusu';

const publication1 = createPublication('Refresh page data');
const publication2 = createPublication('Refresh page data');

console.log(publication1 === publication2); //false

publish(publication, [data])

Parameters:

  • publication: (Required) Object - Publication object created using the api createPublication()
  • [data]: (Optional) Any - The data is passed as is to the subscribers listening to the publication. Its a way of passing data to the subscribers.

publish method calls all the subscribers subscribed to the publication (provided as a first argument). It calls the subscribers with the data.

import { publish } from 'pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

const RefreshPageDataButton = ({ company }) => (
  <button
    onClick={()=> {
      // Publish the data 
      publish(publication, {asOfDate: new Date() };
    }}
  >
    Refresh
  </button>
);

export default RefreshPageDataButton;

subscribe(publication, subscriber)

Parameters:

  • publication: (Required) Object - Publication object created using the api createPublication
  • subscriber: (Required) Function - A subscriber function which will be called by the publisher. This function will receive the data published by the publisher.

Return value: Function - A function when called then the subscriber is unsubscribed and no longer called by the publisher.

Using HOC withSubscribe or hook useSubscribe removes the need of unsubscribe implementation, which is explained in the later sections.

import { subscribe } from 'pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

class DashboardCompanySatistics extends React.Component {
  constructor(props, context) {
    super(props, context);

    // Subscribe to the publication
    this.unsubscribe = props.subscribe(refreshPageDataPublication, this.refreshData);
  }

  refreshData = ({ asOfDate }) => {
    // load the data (may be using redux)
  }

  componentWillUnmount() {
    // Unsubscribe from the publication
    if(this.unsubscribe) {
      this.unsubscribe();
    }

    // Note: 
    // Using HOC `withSubscribe` or hook `useSubscribe` removes the need of above unsubscribe implementation, which is explained in the later sections. 
  }
  
  render() {
    return (
      <section>
        // render the statistics here ...
      </section>
    );
  }
}

export default DashboardCompanySatistics;

withSubscribe(Component)

Parameters:

  • Component: (Required) - React Component

withSubscribe supplies a function subscribe as a property to the React Component. The Component can subscribe to the publication and can receive the data using this function, whenver the publisher publishes it.

withSubscribe makes sure that all the subscriptions are removed/unsubscribed before the component is unmounted. This way the consumer React Component can use the props.subscribe, even multiple times, without worrying about unsubscribing before it is unmounted.

import { withSubscribe } from 'react-pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

class DashboardCompanySatistics extends React.Component {
  constructor(props, context) {
    super(props, context);
    props.subscribe(refreshPageDataPublication, this.refreshData);
  }

  refreshData = ({ asOfDate }) => {
    // load the data (may be using redux)
  }
  
  render() {
    return (
      <section>
        // render the statistics here ...
      </section>
    );
  }
}

export default withSubscribe(DashboardCompanySatistics);

Unsubscribing explicitly

props.subscribe, when called, returns a function which can be called to unsubscribe from the publication. Sometimes component may need to unsubscribe based on some condition or action, for those cases the function returned by props.subscribe can be called to unsubscribe.

import { withSubscribe } from 'react-pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

class DashboardCompanySatistics extends React.Component {
  constructor(props, context) {
    super(props, context);

    // Assign the unsubscriber function to the class member/variable
    this.unsubscribeFromRefreshPublication = props.subscribe(refreshPageDataPublication, this.refreshData);
  }

  refreshData = ({ asOfDate }) => {
    // load the data (may be using redux)
  }

  onSomeAction = () => {
    // Unsubscribe from publication
    this.unsubscribeFromRefreshPublication();
  }
  
  render() {
    return (
      <section>
        // render the statistics here ...
      </section>
    );
  }
}

export default withSubscribe(DashboardCompanySatistics);

useSubscribe()

useSubscribe hook returns a function subscribe. The Component can subscribe to the publication and can receive the data using this subscribe function, whenver the publisher publishes it.

useSubscribe makes sure that all the subscriptions are removed/unsubscribed before the component is unmounted. This way the consumer React Component can use the subscribe, even multiple times, without worrying about unsubscribing before it is unmounted.

import { useSubscribe } from 'react-pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

const DashboardCompanySatistics = () => {
  const subscribe = useSubscribe();
  
  useEffect(() => {
    const refreshData = ({ asOfDate }) => {
      // load the data (may be using redux)
    }

    subscribe(refreshPageDataPublication, refreshData);
  }
   
  return (
    <section>
      // render the statistics here ...
    </section>
  );
};

export default DashboardCompanySatistics;

Unsubscribing explicitely

subscribe, when called, returns a function which can be called to unsubscribe from the publication. Sometimes component may need to unsubscribe based on some condition or action, for those cases the function returned by subscribe can be called to unsubscribe.

import { useSubscribe } from 'react-pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

const DashboardCompanySatistics = () => {
  const ref = useRef({ unsubscribeFromRefreshPublication: () => {} });
  const subscribe = useSubscribe();
  
  useEffect(() => {
    const refreshData = ({ asOfDate }) => {
      // load the data (may be using redux)
    }

    ref.current.unsubscribeFromRefreshPublication = subscribe(refreshPageDataPublication, refreshData);
  }
  
  const onSomeAction = () => {
    // Unsubscribe from publication
    ref.current.unsubscribeFromRefreshPublication();
  }
   
  return (
    <section>
      // render the statistics here ...
    </section>
  );
};

export default DashboardCompanySatistics;

Migrating from 2.0 to 2.1

Breaking change

  • The version 2.1 will need pusu as a separate dependency to be installed
  • The version 2.1 will allow only one parameter while publishing the data & subscribing to the data.

2.0

The version 2.0 were allowing more than one parameters while publishing the data.

In the example below, publisher is publishing date and company id as two different parameters.

import { publish } from 'pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

const RefreshPageDataButton = ({ company }) => (
  <button
    onClick={()=> {
      // Publish the data 
      publish(publication, new Date(), company._id);
    }}
  >
    Refresh
  </button>
);

export default RefreshPageDataButton;

The subscriber receives two arguments as date and company id.

import { useSubscribe } from 'react-pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

const DashboardCompanySatistics = () => {
  const subscribe = useSubscribe();
  
  useEffect(() => {
    const refreshData = (asOf, companyId) => {
      // load the data (may be using redux)
    }

    subscribe(refreshPageDataPublication, refreshData);
  }
   
  return (
    <section>
      // render the statistics here ...
    </section>
  );
};

export default DashboardCompanySatistics;

2.1

The version 2.1 will allow only one parameter while publishing the data & subscribing to the data.

In the example below, publisher is publishing one JSON object consisting of date and company id.

import { publish } from 'pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

const RefreshPageDataButton = ({ company }) => (
  <button
    onClick={()=> {
      // Publish the data 
      publish(publication, { asOfDate: new Date(), companyId: company._id });
    }}
  >
    Refresh
  </button>
);

export default RefreshPageDataButton;

The subscriber receives it as the same JSON object consisting of date and company id.

import { withSubscribe } from 'react-pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

class DashboardCompanySatistics extends React.Component {
  constructor(props, context) {
    super(props, context);
    props.subscribe(refreshPageDataPublication, this.refreshData);
  }

  refreshData = ({ asOfDate, companyId }) => {
    // load the data (may be using redux)
  }
  
  render() {
    return (
      <section>
        // render the statistics here ...
      </section>
    );
  }
}

export default withSubscribe(DashboardCompanySatistics);
import { useSubscribe } from 'react-pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

const DashboardCompanySatistics = () => {
  const subscribe = useSubscribe();
  
  useEffect(() => {
    const refreshData = ({ asOfDate, companyId }) => {
      // load the data (may be using redux)
    }

    subscribe(refreshPageDataPublication, refreshData);
  }
   
  return (
    <section>
      // render the statistics here ...
    </section>
  );
};

export default DashboardCompanySatistics;

Migrating from 1.1 to 1.2

Breaking change

  • The version 1.2 will need pusu as a separate dependency to be installed
  • The version 1.2 will allow only one parameter while publishing the data & subscribing to the data.

1.1

The version 1.1 wes allowing more than one parameters while publishing the data.

In the example below, publisher is publishing date and company id as two different parameters.

import { publish } from 'pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

const RefreshPageDataButton = ({ company }) => (
  <button
    onClick={()=> {
      // Publish the data 
      publish(publication, new Date(), company._id);
    }}
  >
    Refresh
  </button>
);

export default RefreshPageDataButton;

The subscriber receives two arguments as date and company id.

import { useSubscribe } from 'react-pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

const DashboardCompanySatistics = () => {
  const subscribe = useSubscribe();
  
  useEffect(() => {
    const refreshData = (asOf, companyId) => {
      // load the data (may be using redux)
    }

    subscribe(refreshPageDataPublication, refreshData);
  }
   
  return (
    <section>
      // render the statistics here ...
    </section>
  );
};

export default DashboardCompanySatistics;

1.2

The version 1.2 will allow only one parameter while publishing the data & subscribing to the data.

In the example below, publisher is publishing one JSON object consisting of date and company id.

import { publish } from 'pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

const RefreshPageDataButton = ({ company }) => (
  <button
    onClick={()=> {
      // Publish the data 
      publish(publication, { asOfDate: new Date(), companyId: company._id });
    }}
  >
    Refresh
  </button>
);

export default RefreshPageDataButton;

The subscriber receives it as the same JSON object consisting of date and company id.

import { withSubscribe } from 'react-pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

class DashboardCompanySatistics extends React.Component {
  constructor(props, context) {
    super(props, context);
    props.subscribe(refreshPageDataPublication, this.refreshData);
  }

  refreshData = ({ asOfDate, companyId }) => {
    // load the data (may be using redux)
  }
  
  render() {
    return (
      <section>
        // render the statistics here ...
      </section>
    );
  }
}

export default withSubscribe(DashboardCompanySatistics);
import { useSubscribe } from 'react-pusu';
import refreshPageDataPublication from './publications/refresh-page-data-publication';

const DashboardCompanySatistics = () => {
  const subscribe = useSubscribe();
  
  useEffect(() => {
    const refreshData = ({ asOfDate, companyId }) => {
      // load the data (may be using redux)
    }

    subscribe(refreshPageDataPublication, refreshData);
  }
   
  return (
    <section>
      // render the statistics here ...
    </section>
  );
};

export default DashboardCompanySatistics;

License

MIT