Publisher subscriber pattern in React.js
Tags: react, javascript
Published: 2020-09-01 14:08:49

---
title: Publisher subscriber pattern in React.js
published: true
description: Publisher subscriber pattern is a design pattern which is similar to observer pattern. In this blog, we will learn how to implement it in react without using any third-party library.
tags: reactjs, javascript
//cover_image: https://direct_url_to_image.jpg
---
Last week I learnt a pattern called Publisher subscriber(Pub-Sub) pattern and tried to implement it in react. This can easily be done with React's context API or any third party library like Redux,  but I took a different approach.

> ***tl;dr:*** *NOTE:* This code is not production ready. Complete working app can be found [here](https://codesandbox.io/s/pubsub-pattern-5ez3w)

### What is Pub/Sub pattern?

According to Wikipedia

> Pub-Sub is a messaging pattern where senders of messages, called publishers, do not program the messages to be sent directly to specific receivers, called subscribers, but instead categorize published messages into classes without knowledge of which subscribers, if any, there may be. Similarly, subscribers express interest in one or more classes and only receive messages that are of interest, without knowledge of which publishers, if any, there are.

In simple words, the publisher and subscriber are unaware of each other. All the communication between them is taken through events which are emitted from the publisher and notifies subscriber. As shown bellow

<figure class="image">
  <img src="https://dev-to-uploads.s3.amazonaws.com/i/2y38z9unetctcz5ork71.gif" alt="img">
  <figcaption>Pubsub pattern source <a herf="https://docs.microsoft.com/en-us/previous-versions/msp-n-p/ff649664(v=pandp.10)">msd blog</a></figcaption>
</figure>

### Implementing this in React

I have tried to use the Pub-Sub pattern to react in the most simplified manner that I could do with only two events (on and emit). 

In this example, I'll be creating a simple modal which will act as a subscriber. Let's get started:

```jsx 
export const Modal = () => {
  const [content, setContent] = useState("no content");
  const [showModal, setShowModal] = useState(false);

  const setMessage = (message) => {
    setContent(message);
    setShowModal(true);
  };
  const clearMessage = () => {
    setContent("");
    setShowModal(false);
  };

  if (showModal) {
    return (
      <div>
        <h2>{content}</h2>
        <button onClick={clearMessage}>Close Modal </button>
      </div>
    );
  }
  return null;
};
```

Then I need an event bus which will be solely responsible for passing messages around. Here it is:

```javascript

const event = {
  list: new Map(),
  on(eventType, eventAction) {
    this.list.has(eventType) || this.list.set(eventType, []);
    if (this.list.get(eventType)) this.list.get(eventType).push(eventAction);
    return this;
  },

  emit(eventType, ...args) {
    this.list.get(eventType) &&
      this.list.get(eventType).forEach((cb) => {
        cb(...args);
      });
  }
};

```

Here I have on event actions ``on`` and ``emit`` for a more complex system you can other event systems you can add other events such as ``clear``, ``off`` etc.

Once we have our event system on its place let hook this event system in our modal 

```jsx 
export const Modal = () => {
  const [content, setContent] = useState("no content");
  const [showModal, setShowModal] = useState(false);

  const setMessage = (message) => {
    setContent(message);
    setShowModal(true);
  };
  const clearMessage = () => {
    setContent("");
    setShowModal(false);
  };

  useEffect(() => {
    event.on("showModal", setMessage).on("clearAllMessage", clearMessage);
  }, []);
  if (showModal) {
    return (
      <Container>
        <h2>{content}</h2>
        <button onClick={clearMessage}>Close Modal </button>
      </Container>
    );
  }
  return null;
```

Next in order to complete the puzzle we need final pice that is Publisher which will emit the events 

```javascript

export const ModalPublisher = {
  message: (content) => {
    event.emit("showModal", content);
  },
  clearAllMessage: () => {
    event.emit("clearAllMessage");
  }
};

```
Okay once everything is on the place you can now we can use it in `App.js`

```jsx

function App() {
  return (
    <div className="App">
      <Modal showModal={true} />
      <h1
        onClick={() => {
          ModalPublisher.message("this is the content from App");
        }}
      >
        Hello CodeSandbox
      </h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

```
###Conclusion

This code is still not production-ready still there are many edge case to cover. I have used this pattern for Modal and toast.

####Comments?

* Do you use like this pattern? 
* What else this pattern can be used for?