フロントエンド開発といえば。
react アプリの初期化( npm init vite@latest <アプリ名> )

Reactなのに EventEmitter 使うパターン

● eventemitter3 のインストール

useState や useImperativeHandle を使わずに、コンポーネントから別のコンポーネントの関数を実行したい場合に EventEmitter を使うというパターンがあります。

npm install eventemitter3

EventEmitterParentComponent.tsx

import { FC } from 'react';
import { EventEmitterChild1Component } from './EventEmitterChild1Component';
import { EventEmitterChild2Component } from './EventEmitterChild2Component';
import EventEmitter from 'eventemitter3';

export const emitter = new EventEmitter();

export const EventEmitterParentComponent: FC = () => {
  return (
    <div>
      <EventEmitterChild1Component />
      <EventEmitterChild2Component />
    </div>
  );
};

ParentComponent と命名していますが、親子関係は全く関係ありません。
アプリのどこかで

import EventEmitter from 'eventemitter3';
export const emitter = new EventEmitter();

できていればokです。

EventEmitterChild1Component.tsx

import { FC, useEffect } from 'react';
import { emitter } from './EventEmitterParentComponent';

export const EventEmitterChild1Component: FC = () => {
  const showAlert = () => {
    alert('発火しました!');
  };

  useEffect(() => {
    emitter.on('eventName', showAlert);

    // cleanup
    return () => {
      emitter.off('eventName', showAlert);
    };
  });

  return <div>EventEmitterChild1Component</div>;
};

EventEmitterChild2Component.tsx

import { FC } from 'react';
import { emitter } from './EventEmitterParentComponent';

export const EventEmitterChild2Component: FC = () => {
  const handleClick = () => {
    emitter.emit('eventName');
  };

  return (
    <div>
      <button onClick={handleClick}>ボタンです</button>
    </div>
  );
};

オプションなど詳しくはこちら
https://qiita.com/twrcd1227/items/e03111230dad483129ab

● イベントが登録されているかどうかを調べる

const EventEmitter = require('events');
const emitter = new EventEmitter();

// テスト用のイベントリスナーを登録
emitter.on('testEvent', () => console.log('test'));

// 方法1: listenerCount() - リスナーの数を取得
const count = emitter.listenerCount('testEvent');
console.log('Listener count:', count);  // 1

// 方法2: listeners() - リスナー関数の配列を取得
const listeners = emitter.listeners('testEvent');
console.log('Has listeners:', listeners.length > 0);  // true

// 方法3: eventNames() - 登録済みイベント名の配列を取得
const events = emitter.eventNames();
console.log('Has event:', events.includes('testEvent'));  // true

// 実践的な使用例
function safeEmit(emitter, eventName, ...args) {
  if (emitter.listenerCount(eventName) > 0) {
    emitter.emit(eventName, ...args);
    return true;
  }
  return false;
}

// 使用例
const wasEmitted = safeEmit(emitter, 'testEvent');  // true
const noListener = safeEmit(emitter, 'nonexistent'); // false

● EventEmitterとは

https://tinyurl.com/248kr4oy

● Typesafe Event Emitter

https://typescript-jp.gitbook.io/deep-dive/main-1/typed-event

No.2404
11/08 19:51

edit