UNPKG

@react-navigation/core

Version:

Core utilities for building navigators

98 lines (96 loc) 2.7 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 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