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
https://typescript-jp.gitbook.io/deep-dive/main-1/typed-event