useEventEmitter

Notification of events between multiple components can sometimes be a pain, and EventEmitter makes this process even easier.

Reference: useEventEmitter

The source code

import { useRef, useEffect } from "react";

type Subscription<T> = (val: T) = > void;

export class EventEmitter<T> {
  // Use Set to store subscription callbacks
  private subscriptions = new Set<Subscription<T>>();

  // Iterate over the callback function
  emit = (val: T) = > {
    for (const subscription of this.subscriptions) { subscription(val); }}; useSubscription =(callback: Subscription<T>) = > {
    const callbackRef = useRef<Subscription<T>>();
    callbackRef.current = callback;
    useEffect(() = > {
      / / subscribe
      function subscription(val: T) {
        if(callbackRef.current) { callbackRef.current(val); }}this.subscriptions.add(subscription);
      return () = > {
        this.subscriptions.delete(subscription); }; } []); }; }export default function useEventEmitter<T = void> () {
  const ref = useRef<EventEmitter<T>>();
  if(! ref.current) { ref.current =new EventEmitter();
  }
  return ref.current;
}
Copy the code

use

import React, { useRef, FC } from "react";
import { useEventEmitter } from "ahooks";
import { EventEmitter } from "ahooks/lib/useEventEmitter";

const MessageBox: FC<{
  focus$: EventEmitter<void>; } > =function (props) {
  return (
    <div style={{ paddingBottom: 24}} >
      <p>You received a message</p>
      <button
        type="button"
        onClick={()= > {
          props.focus$.emit();
        }}>
        Reply
      </button>
    </div>
  );
};

const InputBox: FC<{
  focus$: EventEmitter<void>; } > =function (props) {
  const inputRef = useRef<any> ();/ / =. = useSubscription and scription returned by instances of EventEmitter are not supported by normal hooks. This gives access to the callback collection of the instance store
  props.focus$.useSubscription(() = > {
    inputRef.current.focus();
  });
  return (
    <input
      ref={inputRef}
      placeholder="Enter reply"
      style={{ width: "100% ",padding: "4px}} "/ >
  );
};

export default function () {
  const focus$ = useEventEmitter();
  return (
    <>
      <MessageBox focus$={focus$} />
      <InputBox focus$={focus$} />
    </>
  );
}
Copy the code

Comparing eventemitter3.js shows that there are many more methods worth extending