@react-navigation/core
Version:
Core utilities for building navigators
98 lines (96 loc) • 2.7 kB
JavaScript
;
import * as React from 'react';
/**
* Hook to manage the event system used by the navigator to notify screens of various events.
*/
export function useEventEmitter(listen) {
const listenRef = React.useRef(listen);
React.useEffect(() => {
listenRef.current = listen;
});
const listeners = React.useRef(Object.create(null));
const create = React.useCallback(target => {
const removeListener = (type, callback) => {
const callbacks = listeners.current[type] ? listeners.current[type][target] : undefined;
if (!callbacks) {
return;
}
const index = callbacks.indexOf(callback);
if (index > -1) {
callbacks.splice(index, 1);
}
};
const addListener = (type, callback) => {
listeners.current[type] = listeners.current[type] || {};
listeners.current[type][target] = listeners.current[type][target] || [];
listeners.current[type][target].push(callback);
let removed = false;
return () => {
// Prevent removing other listeners when unsubscribing same listener multiple times
if (!removed) {
removed = true;
removeListener(type, callback);
}
};
};
return {
addListener,
removeListener
};
}, []);
const emit = React.useCallback(({
type,
data,
target,
canPreventDefault
}) => {
const items = listeners.current[type];
// Copy the current list of callbacks in case they are mutated during execution
let callbacks;
if (items !== undefined) {
callbacks = target !== undefined ? items[target]?.slice() : [].concat(...Object.keys(items).map(t => items[t])).filter((cb, i, self) => self.lastIndexOf(cb) === i);
}
const descriptors = {
type: {
enumerable: true,
value: type
}
};
if (target !== undefined) {
descriptors.target = {
enumerable: true,
value: target
};
}
if (data !== undefined) {
descriptors.data = {
enumerable: true,
value: data
};
}
let defaultPrevented = false;
if (canPreventDefault) {
descriptors.defaultPrevented = {
enumerable: true,
get() {
return defaultPrevented;
}
};
descriptors.preventDefault = {
enumerable: true,
value() {
defaultPrevented = true;
}
};
}
const event = Object.defineProperties({}, descriptors);
listenRef.current?.(event);
callbacks?.forEach(cb => cb(event));
return event;
}, []);
return React.useMemo(() => ({
create,
emit
}), [create, emit]);
}
//# sourceMappingURL=useEventEmitter.js.map