# EventEmitter Pattern with React

A simple EventEmmiter class module:

class EventEmitter {
  constructor() {
    this.events = {};
  }

  on(type, callback) {
    if (!Object.prototype.hasOwnProperty.call(this.events, type)) {
      this.events[type] = [];
    }

    this.events[type].push(callback);
  }

  emit(type, payload) {
    if (this.events[type]) {
      this.events[type].forEach((callback) => {
        callback(payload);
      });
    }
  }

  once() {
    // Feature we can implement to activate listener callback only on the
    // first emit of a specific type
  }
}

export { EventEmitter }

Say we have a parent component that emits events, and a child component that listens to this event and performs an action

Parent component:

class ParentComponent extends Component {
  state = {}

  // Instantiate eventEmitter in instance variable to ensure that
  // each component load works with an eventEmitter in a fresh state,
  // i.e. events registered in the past would be cleared
  eventEmitter = new EventEmitter()

  render() {
    return (
      <div>
        <ChildComponent
          eventEmitter={this.eventEmitter}
        />
        <button
          onClick={() => {this.eventEmitter.emit("myEvent", payloadObj)}}
        />
          Emit
        </button>
      </div>
    )
  }
}

Child Component:

class ChildComponent extends Component {
  state = {}

  myEventCallback = (payload) => {
    console.log("myEvent", payload)
  }

  registerEventListeners = () => {
    const eventEmitter = this.props.eventEmitter;
    eventEmitter.on("myEvent", this.myEventCallback.bind(this, payload))
  }

  componentDidMount() => {
    this.registerEventListeners();
  }
}
Tags:
react