useEventEmitter
在多个组件之间进行事件通知有时会让人非常头疼,借助 EventEmitter ,可以让这一过程变得更加简单。
源码
import { useRef, useEffect } from "react";
type Subscription<T> = (val: T) => void;
export class EventEmitter<T> {
// 采用Set存储订阅回调
private subscriptions = new Set<Subscription<T>>();
// 遍历回调函数
emit = (val: T) => {
for (const subscription of this.subscriptions) {
subscription(val);
}
};
useSubscription = (callback: Subscription<T>) => {
const callbackRef = useRef<Subscription<T>>();
callbackRef.current = callback;
useEffect(() => {
// 订阅
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;
}
复制代码
使用
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>();
// =。=这里使用的是EventEmitter的实例返回的useSubscription,与一般hooks用法不同。这样就能访问到实例存储的回调集合
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$} />
</>
);
}
复制代码
对比 eventEmitter3.js 可以看出,还有非常多方法值得扩展
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END