/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import * as React from 'react';
import * as ReactDOM from 'react-dom';
const {useLayoutEffect, useRef} = React;
const {unstable_createEventHandle} = ReactDOM;
type UseEventHandle = {
setListener: (
target: EventTarget,
null | ((SyntheticEvent<EventTarget>) => void),
) => void,
clear: () => void,
};
export default function useEvent(
event: string,
options?: {
capture?: boolean,
},
): UseEventHandle {
const handleRef = useRef<UseEventHandle | null>(null);
let useEventHandle = handleRef.current;
if (useEventHandle === null) {
const setEventHandle = unstable_createEventHandle(event, options);
const clears = new Map<EventTarget, () => void>();
useEventHandle = {
setListener(
target: EventTarget,
callback: null | ((SyntheticEvent<EventTarget>) => void),
): void {
let clear = clears.get(target);
if (clear !== undefined) {
clear();
}
if (callback === null) {
clears.delete(target);
return;
}
clear = setEventHandle(target, callback);
clears.set(target, clear);
},
clear(): void {
clears.forEach(c => {
c();
});
clears.clear();
},
};
handleRef.current = useEventHandle;
}
useLayoutEffect(() => {
return () => {
if (useEventHandle !== null) {
useEventHandle.clear();
}
handleRef.current = null;
};
}, [useEventHandle]);
return useEventHandle;
}