UNPKG

6.6 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = useLinking;
7
8var React = _interopRequireWildcard(require("react"));
9
10var _reactNative = require("react-native");
11
12var _core = require("@react-navigation/core");
13
14var _extractPathFromURL = _interopRequireDefault(require("./extractPathFromURL"));
15
16function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
18function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
19
20function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
21
22let isUsingLinking = false;
23
24function useLinking(ref, {
25 enabled = true,
26 prefixes,
27 config,
28 getInitialURL = () => Promise.race([_reactNative.Linking.getInitialURL(), new Promise(resolve => // Timeout in 150ms if `getInitialState` doesn't resolve
29 // Workaround for https://github.com/facebook/react-native/issues/25675
30 setTimeout(resolve, 150))]),
31 subscribe = listener => {
32 const callback = ({
33 url
34 }) => listener(url);
35
36 const subscription = _reactNative.Linking.addEventListener('url', callback);
37
38 return () => {
39 // https://github.com/facebook/react-native/commit/6d1aca806cee86ad76de771ed3a1cc62982ebcd7
40 if (subscription !== null && subscription !== void 0 && subscription.remove) {
41 subscription.remove();
42 } else {
43 _reactNative.Linking.removeEventListener('url', callback);
44 }
45 };
46 },
47 getStateFromPath = _core.getStateFromPath,
48 getActionFromState = _core.getActionFromState
49}) {
50 React.useEffect(() => {
51 if (enabled !== false && isUsingLinking) {
52 throw new 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 are not using both 'linking' prop and 'useLinking'", "- You don't have 'useLinking' in multiple components", _reactNative.Platform.OS === 'android' ? "- You have set 'android:launchMode=singleTask' in the '<activity />' section of the 'AndroidManifest.xml' file to avoid launching multiple instances" : ''].join('\n').trim());
53 } else {
54 isUsingLinking = enabled !== false;
55 }
56
57 return () => {
58 isUsingLinking = false;
59 };
60 }); // We store these options in ref to avoid re-creating getInitialState and re-subscribing listeners
61 // This lets user avoid wrapping the items in `React.useCallback` or `React.useMemo`
62 // Not re-creating `getInitialState` is important coz it makes it easier for the user to use in an effect
63
64 const enabledRef = React.useRef(enabled);
65 const prefixesRef = React.useRef(prefixes);
66 const configRef = React.useRef(config);
67 const getInitialURLRef = React.useRef(getInitialURL);
68 const getStateFromPathRef = React.useRef(getStateFromPath);
69 const getActionFromStateRef = React.useRef(getActionFromState);
70 React.useEffect(() => {
71 enabledRef.current = enabled;
72 prefixesRef.current = prefixes;
73 configRef.current = config;
74 getInitialURLRef.current = getInitialURL;
75 getStateFromPathRef.current = getStateFromPath;
76 getActionFromStateRef.current = getActionFromState;
77 });
78 const getInitialState = React.useCallback(() => {
79 let state;
80
81 if (enabledRef.current) {
82 const url = getInitialURLRef.current();
83
84 if (url != null && typeof url !== 'string') {
85 return url.then(url => {
86 const path = url ? (0, _extractPathFromURL.default)(prefixesRef.current, url) : null;
87 return path ? getStateFromPathRef.current(path, configRef.current) : undefined;
88 });
89 }
90
91 const path = url ? (0, _extractPathFromURL.default)(prefixesRef.current, url) : null;
92 state = path ? getStateFromPathRef.current(path, configRef.current) : undefined;
93 }
94
95 const thenable = {
96 then(onfulfilled) {
97 return Promise.resolve(onfulfilled ? onfulfilled(state) : state);
98 },
99
100 catch() {
101 return thenable;
102 }
103
104 };
105 return thenable;
106 }, []);
107 React.useEffect(() => {
108 const listener = url => {
109 if (!enabled) {
110 return;
111 }
112
113 const path = (0, _extractPathFromURL.default)(prefixesRef.current, url);
114 const navigation = ref.current;
115
116 if (navigation && path) {
117 const state = getStateFromPathRef.current(path, configRef.current);
118
119 if (state) {
120 // Make sure that the routes in the state exist in the root navigator
121 // Otherwise there's an error in the linking configuration
122 const rootState = navigation.getRootState();
123
124 if (state.routes.some(r => !(rootState !== null && rootState !== void 0 && rootState.routeNames.includes(r.name)))) {
125 console.warn("The navigation state parsed from the URL contains routes not present in the root navigator. This usually means that the linking configuration doesn't match the navigation structure. See https://reactnavigation.org/docs/configuring-links for more details on how to specify a linking configuration.");
126 return;
127 }
128
129 const action = getActionFromStateRef.current(state, configRef.current);
130
131 if (action !== undefined) {
132 try {
133 navigation.dispatch(action);
134 } catch (e) {
135 // Ignore any errors from deep linking.
136 // This could happen in case of malformed links, navigation object not being initialized etc.
137 console.warn("An error occurred when trying to handle the link '".concat(path, "': ").concat(e.message));
138 }
139 } else {
140 navigation.resetRoot(state);
141 }
142 }
143 }
144 };
145
146 return subscribe(listener);
147 }, [enabled, ref, subscribe]);
148 return {
149 getInitialState
150 };
151}
152//# sourceMappingURL=useLinking.native.js.map
\No newline at end of file