useEventEmitter

A basic eventemitter

useEventEmitter creates a lightweight publish/subscribe event system scoped to your component. It returns a tuple of three items: an event function to register listeners (each returning a disposable), a fire function to broadcast a value to all listeners, and a dispose function to remove all listeners at once. Listener references are stored in a ref, so the emitter identity is stable across renders.

When to Use

  • Coordinating communication between sibling components or decoupled modules without lifting state up
  • Building custom notification or messaging systems within a React tree
  • Implementing undo/redo or command patterns where multiple subscribers react to dispatched events

Notes

  • Disposable pattern: Each call to the event function returns an object with a dispose() method, allowing you to remove individual listeners without affecting others.
  • No automatic cleanup: Listeners are not removed on unmount automatically. Call dispose() in a useEffect cleanup or use useUnmount to prevent memory leaks.
  • The emitter supports generic typing for both the event payload and an optional second argument.

Usage

Live Editor
function Demo() {
  const [state, setState] = useState(0);
  const [event, fire, dispose] = useEventEmitter<number>();

  const event1 = useRef<IDisposable>();
  useEffect(() => {
    event((val) => {
      setState(s => s + val);
    });
    event1.current = event(val => setState(s => s + val + 10));
  }, [event]);

  return (
    <div>
      <div>state: {state}</div>
      <button onClick={() => fire(1)}>fire</button>
      <button onClick={() => dispose()}>disposeALL</button>
      <button onClick={() => event1.current?.dispose()}>disposeOne</button>
    </div>
  );
};

render(<Demo/>);
Result

API

useEventEmitter

Returns

readonly [UseEventEmitterEvent<T, U>, (arg1: T, arg2: U) => void, () => void]: A tuple with the following elements:

  • a function to add lisenter.
  • fire functiion. stop functiion

Arguments