UNPKG

expo-router

Version:

Expo Router is a file-based router for React Native and web applications.

144 lines (142 loc) • 5.86 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "useLinking", { enumerable: true, get: function() { return useLinking; } }); function _react() { const data = require("react"); _react = function() { return data; }; return data; } function _reactnative() { const data = require("react-native"); _reactnative = function() { return data; }; return data; } const _createSeededNavigationState = require("../global-state/createSeededNavigationState"); const _getRouteInfoFromState = require("../global-state/getRouteInfoFromState"); const _routerConfigContext = require("../global-state/routerConfigContext"); const _routingQueueContext = require("../global-state/routingQueueContext"); const _layoutAnchor = require("../layoutAnchor"); const _native = require("../react-navigation/native"); const _stateKeys = require("../react-navigation/routers/stateKeys"); const _extractPathFromURL = require("./extractPathFromURL"); const _getInitialURLWithTimeout = require("./getInitialURLWithTimeout"); const linkingHandlers = []; function getInitialPath(prefixes, url) { const path = (0, _extractPathFromURL.extractExpoPathFromURL)(prefixes, url); return path.startsWith('/') ? path : `/${path}`; } function useLinking(ref, { prefixes, filter, config, getInitialURL = ()=>(0, _getInitialURLWithTimeout.getInitialURLWithTimeout)(), subscribe = (listener)=>{ const callback = ({ url })=>listener(url); const subscription = _reactnative().Linking.addEventListener('url', callback); // Storing this in a local variable stops Jest from complaining about import after teardown // @ts-expect-error: removeEventListener is not present in newer RN versions const removeEventListener = _reactnative().Linking.removeEventListener?.bind(_reactnative().Linking); return ()=>{ // https://github.com/facebook/react-native/commit/6d1aca806cee86ad76de771ed3a1cc62982ebcd7 if (subscription?.remove) { subscription.remove(); } else { removeEventListener?.('url', callback); } }; }, getStateFromPath = _native.getStateFromPath }) { const routerConfig = (0, _react().use)(_routerConfigContext.RouterConfigContext); const enqueue = (0, _routingQueueContext.useEnqueueRoutingIntent)(); (0, _react().useEffect)(()=>{ if (process.env.NODE_ENV === 'production') { return undefined; } if (linkingHandlers.length) { console.error([ 'Looks like you have configured linking in multiple places. This is likely an error since deep links should only be handled in one place to avoid conflicts. Make sure that:', "- You don't have multiple NavigationContainers in the app", '- Only a single instance of the root component is rendered' ].join('\n').trim()); } const handler = Symbol(); linkingHandlers.push(handler); return ()=>{ const index = linkingHandlers.indexOf(handler); if (index > -1) { linkingHandlers.splice(index, 1); } }; }, []); const getStateFromURL = (0, _react().useEffectEvent)((url)=>{ if (!url || filter && !filter(url)) { return undefined; } const path = (0, _extractPathFromURL.extractExpoPathFromURL)(prefixes, url); if (path !== undefined) { // TODO(@ubax): check if ref.current?.getRootState() can be replaced with the context read const segments = (0, _getRouteInfoFromState.getRouteSegmentsFromState)(ref.current?.getRootState()); return getStateFromPath(path, config, segments); } return undefined; }); const getInitialState = (0, _react().useCallback)(()=>{ const url = getInitialURL(); const createInitialState = (url)=>{ const shouldParseURL = url && (!filter || filter(url)); const parsedState = shouldParseURL ? getStateFromPath(getInitialPath(prefixes, url), config) : undefined; const routeNode = routerConfig?.routeNode; return routeNode ? (0, _layoutAnchor.withLoadedLayouts)(()=>(0, _createSeededNavigationState.createSeededRootState)(parsedState, routeNode)) : (0, _createSeededNavigationState.completeParsedState)(parsedState, _stateKeys.ROOT_CHAIN); }; if (url != null && typeof url !== 'string') { return url.then(createInitialState); } return createInitialState(url); }, [ config, filter, getInitialURL, getStateFromPath, prefixes, routerConfig ]); (0, _react().useEffect)(()=>{ const listener = (url)=>{ const navigation = ref.current; const path = getInitialPath(prefixes, url); const state = navigation ? getStateFromURL(url) : undefined; if (navigation && state) { const rootState = navigation.getRootState(); if (state.routes.some((r)=>!rootState?.routeNames.includes(r.name))) { return; } enqueue({ type: 'NAVIGATE_TO_HREF', payload: { href: path, originalHref: url, options: { event: 'NAVIGATE', __internal__popToNavigator: true } } }); } }; return subscribe(listener); }, [ enqueue, prefixes, ref, subscribe ]); return { getInitialState }; } //# sourceMappingURL=useLinking.native.js.map