UNPKG

@react-navigation/core

Version:

Core utilities for building navigators

99 lines (97 loc) 2.72 kB
"use strict"; 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 const callbacks = target !== undefined ? items[target]?.slice() : [].concat(...Object.keys(items).map(t => items[t])).filter((cb, i, self) => self.lastIndexOf(cb) === i); const event = { get type() { return type; } }; if (target !== undefined) { Object.defineProperty(event, 'target', { enumerable: true, get() { return target; } }); } if (data !== undefined) { Object.defineProperty(event, 'data', { enumerable: true, get() { return data; } }); } if (canPreventDefault) { let defaultPrevented = false; Object.defineProperties(event, { defaultPrevented: { enumerable: true, get() { return defaultPrevented; } }, preventDefault: { enumerable: true, value() { defaultPrevented = true; } } }); } listenRef.current?.(event); callbacks?.forEach(cb => cb(event)); return event; }, []); return React.useMemo(() => ({ create, emit }), [create, emit]); } //# sourceMappingURL=useEventEmitter.js.map