@react-navigation/core 6.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -0
  3. package/lib/commonjs/BaseNavigationContainer.js +393 -0
  4. package/lib/commonjs/BaseNavigationContainer.js.map +1 -0
  5. package/lib/commonjs/CurrentRenderContext.js +21 -0
  6. package/lib/commonjs/CurrentRenderContext.js.map +1 -0
  7. package/lib/commonjs/EnsureSingleNavigator.js +53 -0
  8. package/lib/commonjs/EnsureSingleNavigator.js.map +1 -0
  9. package/lib/commonjs/Group.js +15 -0
  10. package/lib/commonjs/Group.js.map +1 -0
  11. package/lib/commonjs/NavigationBuilderContext.js +23 -0
  12. package/lib/commonjs/NavigationBuilderContext.js.map +1 -0
  13. package/lib/commonjs/NavigationContainerRefContext.js +20 -0
  14. package/lib/commonjs/NavigationContainerRefContext.js.map +1 -0
  15. package/lib/commonjs/NavigationContext.js +20 -0
  16. package/lib/commonjs/NavigationContext.js.map +1 -0
  17. package/lib/commonjs/NavigationHelpersContext.js +21 -0
  18. package/lib/commonjs/NavigationHelpersContext.js.map +1 -0
  19. package/lib/commonjs/NavigationRouteContext.js +20 -0
  20. package/lib/commonjs/NavigationRouteContext.js.map +1 -0
  21. package/lib/commonjs/NavigationStateContext.js +42 -0
  22. package/lib/commonjs/NavigationStateContext.js.map +1 -0
  23. package/lib/commonjs/SceneView.js +97 -0
  24. package/lib/commonjs/SceneView.js.map +1 -0
  25. package/lib/commonjs/Screen.js +15 -0
  26. package/lib/commonjs/Screen.js.map +1 -0
  27. package/lib/commonjs/StaticContainer.js +43 -0
  28. package/lib/commonjs/StaticContainer.js.map +1 -0
  29. package/lib/commonjs/UnhandledActionContext.js +17 -0
  30. package/lib/commonjs/UnhandledActionContext.js.map +1 -0
  31. package/lib/commonjs/checkDuplicateRouteNames.js +31 -0
  32. package/lib/commonjs/checkDuplicateRouteNames.js.map +1 -0
  33. package/lib/commonjs/checkSerializable.js +59 -0
  34. package/lib/commonjs/checkSerializable.js.map +1 -0
  35. package/lib/commonjs/createNavigationContainerRef.js +82 -0
  36. package/lib/commonjs/createNavigationContainerRef.js.map +1 -0
  37. package/lib/commonjs/createNavigatorFactory.js +34 -0
  38. package/lib/commonjs/createNavigatorFactory.js.map +1 -0
  39. package/lib/commonjs/findFocusedRoute.js +22 -0
  40. package/lib/commonjs/findFocusedRoute.js.map +1 -0
  41. package/lib/commonjs/fromEntries.js +19 -0
  42. package/lib/commonjs/fromEntries.js.map +1 -0
  43. package/lib/commonjs/getActionFromState.js +99 -0
  44. package/lib/commonjs/getActionFromState.js.map +1 -0
  45. package/lib/commonjs/getFocusedRouteNameFromRoute.js +23 -0
  46. package/lib/commonjs/getFocusedRouteNameFromRoute.js.map +1 -0
  47. package/lib/commonjs/getPathFromState.js +238 -0
  48. package/lib/commonjs/getPathFromState.js.map +1 -0
  49. package/lib/commonjs/getStateFromPath.js +450 -0
  50. package/lib/commonjs/getStateFromPath.js.map +1 -0
  51. package/lib/commonjs/index.js +227 -0
  52. package/lib/commonjs/index.js.map +1 -0
  53. package/lib/commonjs/isArrayEqual.js +15 -0
  54. package/lib/commonjs/isArrayEqual.js.map +1 -0
  55. package/lib/commonjs/types.js +18 -0
  56. package/lib/commonjs/types.js.map +1 -0
  57. package/lib/commonjs/useChildListeners.js +38 -0
  58. package/lib/commonjs/useChildListeners.js.map +1 -0
  59. package/lib/commonjs/useComponent.js +36 -0
  60. package/lib/commonjs/useComponent.js.map +1 -0
  61. package/lib/commonjs/useCurrentRender.js +33 -0
  62. package/lib/commonjs/useCurrentRender.js.map +1 -0
  63. package/lib/commonjs/useDescriptors.js +141 -0
  64. package/lib/commonjs/useDescriptors.js.map +1 -0
  65. package/lib/commonjs/useEventEmitter.js +118 -0
  66. package/lib/commonjs/useEventEmitter.js.map +1 -0
  67. package/lib/commonjs/useFocusEffect.js +97 -0
  68. package/lib/commonjs/useFocusEffect.js.map +1 -0
  69. package/lib/commonjs/useFocusEvents.js +77 -0
  70. package/lib/commonjs/useFocusEvents.js.map +1 -0
  71. package/lib/commonjs/useFocusedListenersChildrenAdapter.js +57 -0
  72. package/lib/commonjs/useFocusedListenersChildrenAdapter.js.map +1 -0
  73. package/lib/commonjs/useIsFocused.js +47 -0
  74. package/lib/commonjs/useIsFocused.js.map +1 -0
  75. package/lib/commonjs/useKeyedChildListeners.js +35 -0
  76. package/lib/commonjs/useKeyedChildListeners.js.map +1 -0
  77. package/lib/commonjs/useNavigation.js +36 -0
  78. package/lib/commonjs/useNavigation.js.map +1 -0
  79. package/lib/commonjs/useNavigationBuilder.js +480 -0
  80. package/lib/commonjs/useNavigationBuilder.js.map +1 -0
  81. package/lib/commonjs/useNavigationCache.js +122 -0
  82. package/lib/commonjs/useNavigationCache.js.map +1 -0
  83. package/lib/commonjs/useNavigationContainerRef.js +27 -0
  84. package/lib/commonjs/useNavigationContainerRef.js.map +1 -0
  85. package/lib/commonjs/useNavigationHelpers.js +77 -0
  86. package/lib/commonjs/useNavigationHelpers.js.map +1 -0
  87. package/lib/commonjs/useNavigationState.js +41 -0
  88. package/lib/commonjs/useNavigationState.js.map +1 -0
  89. package/lib/commonjs/useOnAction.js +118 -0
  90. package/lib/commonjs/useOnAction.js.map +1 -0
  91. package/lib/commonjs/useOnGetState.js +60 -0
  92. package/lib/commonjs/useOnGetState.js.map +1 -0
  93. package/lib/commonjs/useOnPreventRemove.js +89 -0
  94. package/lib/commonjs/useOnPreventRemove.js.map +1 -0
  95. package/lib/commonjs/useOnRouteFocus.js +45 -0
  96. package/lib/commonjs/useOnRouteFocus.js.map +1 -0
  97. package/lib/commonjs/useOptionsGetters.js +99 -0
  98. package/lib/commonjs/useOptionsGetters.js.map +1 -0
  99. package/lib/commonjs/useRegisterNavigator.js +40 -0
  100. package/lib/commonjs/useRegisterNavigator.js.map +1 -0
  101. package/lib/commonjs/useRoute.js +32 -0
  102. package/lib/commonjs/useRoute.js.map +1 -0
  103. package/lib/commonjs/useRouteCache.js +61 -0
  104. package/lib/commonjs/useRouteCache.js.map +1 -0
  105. package/lib/commonjs/useScheduleUpdate.js +44 -0
  106. package/lib/commonjs/useScheduleUpdate.js.map +1 -0
  107. package/lib/commonjs/useSyncState.js +76 -0
  108. package/lib/commonjs/useSyncState.js.map +1 -0
  109. package/lib/commonjs/validatePathConfig.js +31 -0
  110. package/lib/commonjs/validatePathConfig.js.map +1 -0
  111. package/lib/module/BaseNavigationContainer.js +360 -0
  112. package/lib/module/BaseNavigationContainer.js.map +1 -0
  113. package/lib/module/CurrentRenderContext.js +9 -0
  114. package/lib/module/CurrentRenderContext.js.map +1 -0
  115. package/lib/module/EnsureSingleNavigator.js +38 -0
  116. package/lib/module/EnsureSingleNavigator.js.map +1 -0
  117. package/lib/module/Group.js +8 -0
  118. package/lib/module/Group.js.map +1 -0
  119. package/lib/module/NavigationBuilderContext.js +11 -0
  120. package/lib/module/NavigationBuilderContext.js.map +1 -0
  121. package/lib/module/NavigationContainerRefContext.js +8 -0
  122. package/lib/module/NavigationContainerRefContext.js.map +1 -0
  123. package/lib/module/NavigationContext.js +8 -0
  124. package/lib/module/NavigationContext.js.map +1 -0
  125. package/lib/module/NavigationHelpersContext.js +9 -0
  126. package/lib/module/NavigationHelpersContext.js.map +1 -0
  127. package/lib/module/NavigationRouteContext.js +8 -0
  128. package/lib/module/NavigationRouteContext.js.map +1 -0
  129. package/lib/module/NavigationStateContext.js +27 -0
  130. package/lib/module/NavigationStateContext.js.map +1 -0
  131. package/lib/module/SceneView.js +80 -0
  132. package/lib/module/SceneView.js.map +1 -0
  133. package/lib/module/Screen.js +8 -0
  134. package/lib/module/Screen.js.map +1 -0
  135. package/lib/module/StaticContainer.js +30 -0
  136. package/lib/module/StaticContainer.js.map +1 -0
  137. package/lib/module/UnhandledActionContext.js +4 -0
  138. package/lib/module/UnhandledActionContext.js.map +1 -0
  139. package/lib/module/checkDuplicateRouteNames.js +24 -0
  140. package/lib/module/checkDuplicateRouteNames.js.map +1 -0
  141. package/lib/module/checkSerializable.js +52 -0
  142. package/lib/module/checkSerializable.js.map +1 -0
  143. package/lib/module/createNavigationContainerRef.js +71 -0
  144. package/lib/module/createNavigationContainerRef.js.map +1 -0
  145. package/lib/module/createNavigatorFactory.js +24 -0
  146. package/lib/module/createNavigatorFactory.js.map +1 -0
  147. package/lib/module/findFocusedRoute.js +15 -0
  148. package/lib/module/findFocusedRoute.js.map +1 -0
  149. package/lib/module/fromEntries.js +12 -0
  150. package/lib/module/fromEntries.js.map +1 -0
  151. package/lib/module/getActionFromState.js +92 -0
  152. package/lib/module/getActionFromState.js.map +1 -0
  153. package/lib/module/getFocusedRouteNameFromRoute.js +15 -0
  154. package/lib/module/getFocusedRouteNameFromRoute.js.map +1 -0
  155. package/lib/module/getPathFromState.js +223 -0
  156. package/lib/module/getPathFromState.js.map +1 -0
  157. package/lib/module/getStateFromPath.js +434 -0
  158. package/lib/module/getStateFromPath.js.map +1 -0
  159. package/lib/module/index.js +24 -0
  160. package/lib/module/index.js.map +1 -0
  161. package/lib/module/isArrayEqual.js +8 -0
  162. package/lib/module/isArrayEqual.js.map +1 -0
  163. package/lib/module/types.js +9 -0
  164. package/lib/module/types.js.map +1 -0
  165. package/lib/module/useChildListeners.js +27 -0
  166. package/lib/module/useChildListeners.js.map +1 -0
  167. package/lib/module/useComponent.js +24 -0
  168. package/lib/module/useComponent.js.map +1 -0
  169. package/lib/module/useCurrentRender.js +19 -0
  170. package/lib/module/useCurrentRender.js.map +1 -0
  171. package/lib/module/useDescriptors.js +122 -0
  172. package/lib/module/useDescriptors.js.map +1 -0
  173. package/lib/module/useEventEmitter.js +107 -0
  174. package/lib/module/useEventEmitter.js.map +1 -0
  175. package/lib/module/useFocusEffect.js +83 -0
  176. package/lib/module/useFocusEffect.js.map +1 -0
  177. package/lib/module/useFocusEvents.js +63 -0
  178. package/lib/module/useFocusEvents.js.map +1 -0
  179. package/lib/module/useFocusedListenersChildrenAdapter.js +43 -0
  180. package/lib/module/useFocusedListenersChildrenAdapter.js.map +1 -0
  181. package/lib/module/useIsFocused.js +34 -0
  182. package/lib/module/useIsFocused.js.map +1 -0
  183. package/lib/module/useKeyedChildListeners.js +24 -0
  184. package/lib/module/useKeyedChildListeners.js.map +1 -0
  185. package/lib/module/useNavigation.js +21 -0
  186. package/lib/module/useNavigation.js.map +1 -0
  187. package/lib/module/useNavigationBuilder.js +443 -0
  188. package/lib/module/useNavigationBuilder.js.map +1 -0
  189. package/lib/module/useNavigationCache.js +107 -0
  190. package/lib/module/useNavigationCache.js.map +1 -0
  191. package/lib/module/useNavigationContainerRef.js +12 -0
  192. package/lib/module/useNavigationContainerRef.js.map +1 -0
  193. package/lib/module/useNavigationHelpers.js +59 -0
  194. package/lib/module/useNavigationHelpers.js.map +1 -0
  195. package/lib/module/useNavigationState.js +27 -0
  196. package/lib/module/useNavigationState.js.map +1 -0
  197. package/lib/module/useOnAction.js +103 -0
  198. package/lib/module/useOnAction.js.map +1 -0
  199. package/lib/module/useOnGetState.js +43 -0
  200. package/lib/module/useOnGetState.js.map +1 -0
  201. package/lib/module/useOnPreventRemove.js +68 -0
  202. package/lib/module/useOnPreventRemove.js.map +1 -0
  203. package/lib/module/useOnRouteFocus.js +31 -0
  204. package/lib/module/useOnRouteFocus.js.map +1 -0
  205. package/lib/module/useOptionsGetters.js +83 -0
  206. package/lib/module/useOptionsGetters.js.map +1 -0
  207. package/lib/module/useRegisterNavigator.js +27 -0
  208. package/lib/module/useRegisterNavigator.js.map +1 -0
  209. package/lib/module/useRoute.js +18 -0
  210. package/lib/module/useRoute.js.map +1 -0
  211. package/lib/module/useRouteCache.js +47 -0
  212. package/lib/module/useRouteCache.js.map +1 -0
  213. package/lib/module/useScheduleUpdate.js +29 -0
  214. package/lib/module/useScheduleUpdate.js.map +1 -0
  215. package/lib/module/useSyncState.js +64 -0
  216. package/lib/module/useSyncState.js.map +1 -0
  217. package/lib/module/validatePathConfig.js +24 -0
  218. package/lib/module/validatePathConfig.js.map +1 -0
  219. package/lib/typescript/src/BaseNavigationContainer.d.ts +14 -0
  220. package/lib/typescript/src/CurrentRenderContext.d.ts +9 -0
  221. package/lib/typescript/src/EnsureSingleNavigator.d.ts +13 -0
  222. package/lib/typescript/src/Group.d.ts +6 -0
  223. package/lib/typescript/src/NavigationBuilderContext.d.ts +34 -0
  224. package/lib/typescript/src/NavigationContainerRefContext.d.ts +8 -0
  225. package/lib/typescript/src/NavigationContext.d.ts +24 -0
  226. package/lib/typescript/src/NavigationHelpersContext.d.ts +9 -0
  227. package/lib/typescript/src/NavigationRouteContext.d.ts +7 -0
  228. package/lib/typescript/src/NavigationStateContext.d.ts +45 -0
  229. package/lib/typescript/src/SceneView.d.ts +21 -0
  230. package/lib/typescript/src/Screen.d.ts +6 -0
  231. package/lib/typescript/src/StaticContainer.d.ts +7 -0
  232. package/lib/typescript/src/UnhandledActionContext.d.ts +4 -0
  233. package/lib/typescript/src/checkDuplicateRouteNames.d.ts +2 -0
  234. package/lib/typescript/src/checkSerializable.d.ts +9 -0
  235. package/lib/typescript/src/createNavigationContainerRef.d.ts +3 -0
  236. package/lib/typescript/src/createNavigatorFactory.d.ts +11 -0
  237. package/lib/typescript/src/findFocusedRoute.d.ts +22 -0
  238. package/lib/typescript/src/fromEntries.d.ts +1 -0
  239. package/lib/typescript/src/getActionFromState.d.ts +16 -0
  240. package/lib/typescript/src/getFocusedRouteNameFromRoute.d.ts +2 -0
  241. package/lib/typescript/src/getPathFromState.d.ts +38 -0
  242. package/lib/typescript/src/getStateFromPath.d.ts +32 -0
  243. package/lib/typescript/src/index.d.ts +23 -0
  244. package/lib/typescript/src/isArrayEqual.d.ts +5 -0
  245. package/lib/typescript/src/types.d.ts +485 -0
  246. package/lib/typescript/src/useChildListeners.d.ts +11 -0
  247. package/lib/typescript/src/useComponent.d.ts +2 -0
  248. package/lib/typescript/src/useCurrentRender.d.ts +13 -0
  249. package/lib/typescript/src/useDescriptors.d.ts +89 -0
  250. package/lib/typescript/src/useEventEmitter.d.ts +8 -0
  251. package/lib/typescript/src/useFocusEffect.d.ts +10 -0
  252. package/lib/typescript/src/useFocusEvents.d.ts +12 -0
  253. package/lib/typescript/src/useFocusedListenersChildrenAdapter.d.ts +12 -0
  254. package/lib/typescript/src/useIsFocused.d.ts +5 -0
  255. package/lib/typescript/src/useKeyedChildListeners.d.ts +11 -0
  256. package/lib/typescript/src/useNavigation.d.ts +7 -0
  257. package/lib/typescript/src/useNavigationBuilder.d.ts +223 -0
  258. package/lib/typescript/src/useNavigationCache.d.ts +19 -0
  259. package/lib/typescript/src/useNavigationContainerRef.d.ts +2 -0
  260. package/lib/typescript/src/useNavigationHelpers.d.ts +174 -0
  261. package/lib/typescript/src/useNavigationState.d.ts +9 -0
  262. package/lib/typescript/src/useOnAction.d.ts +25 -0
  263. package/lib/typescript/src/useOnGetState.d.ts +8 -0
  264. package/lib/typescript/src/useOnPreventRemove.d.ts +16 -0
  265. package/lib/typescript/src/useOnRouteFocus.d.ts +14 -0
  266. package/lib/typescript/src/useOptionsGetters.d.ts +12 -0
  267. package/lib/typescript/src/useRegisterNavigator.d.ts +5 -0
  268. package/lib/typescript/src/useRoute.d.ts +8 -0
  269. package/lib/typescript/src/useRouteCache.d.ts +13 -0
  270. package/lib/typescript/src/useScheduleUpdate.d.ts +13 -0
  271. package/lib/typescript/src/useSyncState.d.ts +4 -0
  272. package/lib/typescript/src/validatePathConfig.d.ts +1 -0
  273. package/package.json +73 -0
  274. package/src/BaseNavigationContainer.tsx +453 -0
  275. package/src/CurrentRenderContext.tsx +10 -0
  276. package/src/EnsureSingleNavigator.tsx +53 -0
  277. package/src/Group.tsx +14 -0
  278. package/src/NavigationBuilderContext.tsx +70 -0
  279. package/src/NavigationContainerRefContext.tsx +14 -0
  280. package/src/NavigationContext.tsx +12 -0
  281. package/src/NavigationHelpersContext.tsx +13 -0
  282. package/src/NavigationRouteContext.tsx +10 -0
  283. package/src/NavigationStateContext.tsx +39 -0
  284. package/src/SceneView.tsx +134 -0
  285. package/src/Screen.tsx +17 -0
  286. package/src/StaticContainer.tsx +29 -0
  287. package/src/UnhandledActionContext.tsx +9 -0
  288. package/src/checkDuplicateRouteNames.tsx +33 -0
  289. package/src/checkSerializable.tsx +74 -0
  290. package/src/createNavigationContainerRef.tsx +97 -0
  291. package/src/createNavigatorFactory.tsx +40 -0
  292. package/src/findFocusedRoute.tsx +13 -0
  293. package/src/fromEntries.tsx +13 -0
  294. package/src/getActionFromState.tsx +154 -0
  295. package/src/getFocusedRouteNameFromRoute.tsx +28 -0
  296. package/src/getPathFromState.tsx +297 -0
  297. package/src/getStateFromPath.tsx +575 -0
  298. package/src/index.tsx +23 -0
  299. package/src/isArrayEqual.tsx +7 -0
  300. package/src/types.tsx +645 -0
  301. package/src/useChildListeners.tsx +37 -0
  302. package/src/useComponent.tsx +30 -0
  303. package/src/useCurrentRender.tsx +35 -0
  304. package/src/useDescriptors.tsx +229 -0
  305. package/src/useEventEmitter.tsx +130 -0
  306. package/src/useFocusEffect.tsx +112 -0
  307. package/src/useFocusEvents.tsx +73 -0
  308. package/src/useFocusedListenersChildrenAdapter.tsx +47 -0
  309. package/src/useIsFocused.tsx +43 -0
  310. package/src/useKeyedChildListeners.tsx +40 -0
  311. package/src/useNavigation.tsx +26 -0
  312. package/src/useNavigationBuilder.tsx +640 -0
  313. package/src/useNavigationCache.tsx +159 -0
  314. package/src/useNavigationContainerRef.tsx +17 -0
  315. package/src/useNavigationHelpers.tsx +98 -0
  316. package/src/useNavigationState.tsx +41 -0
  317. package/src/useOnAction.tsx +166 -0
  318. package/src/useOnGetState.tsx +47 -0
  319. package/src/useOnPreventRemove.tsx +99 -0
  320. package/src/useOnRouteFocus.tsx +47 -0
  321. package/src/useOptionsGetters.tsx +98 -0
  322. package/src/useRegisterNavigator.tsx +29 -0
  323. package/src/useRoute.tsx +22 -0
  324. package/src/useRouteCache.tsx +55 -0
  325. package/src/useScheduleUpdate.tsx +32 -0
  326. package/src/useSyncState.tsx +74 -0
  327. package/src/validatePathConfig.tsx +32 -0
@@ -0,0 +1,159 @@
1
+ import {
2
+ CommonActions,
3
+ NavigationAction,
4
+ NavigationState,
5
+ ParamListBase,
6
+ Router,
7
+ } from '@react-navigation/routers';
8
+ import * as React from 'react';
9
+
10
+ import NavigationBuilderContext from './NavigationBuilderContext';
11
+ import type { NavigationHelpers, NavigationProp } from './types';
12
+ import type { NavigationEventEmitter } from './useEventEmitter';
13
+
14
+ type Options<
15
+ State extends NavigationState,
16
+ EventMap extends Record<string, any>
17
+ > = {
18
+ state: State;
19
+ getState: () => State;
20
+ navigation: NavigationHelpers<ParamListBase> &
21
+ Partial<NavigationProp<ParamListBase, string, any, any, any>>;
22
+ setOptions: (
23
+ cb: (options: Record<string, object>) => Record<string, object>
24
+ ) => void;
25
+ router: Router<State, NavigationAction>;
26
+ emitter: NavigationEventEmitter<EventMap>;
27
+ };
28
+
29
+ type NavigationCache<
30
+ State extends NavigationState,
31
+ ScreenOptions extends {},
32
+ EventMap extends Record<string, any>
33
+ > = Record<
34
+ string,
35
+ NavigationProp<ParamListBase, string, State, ScreenOptions, EventMap>
36
+ >;
37
+
38
+ /**
39
+ * Hook to cache navigation objects for each screen in the navigator.
40
+ * It's important to cache them to make sure navigation objects don't change between renders.
41
+ * This lets us apply optimizations like `React.memo` to minimize re-rendering screens.
42
+ */
43
+ export default function useNavigationCache<
44
+ State extends NavigationState,
45
+ ScreenOptions extends {},
46
+ EventMap extends Record<string, any>
47
+ >({
48
+ state,
49
+ getState,
50
+ navigation,
51
+ setOptions,
52
+ router,
53
+ emitter,
54
+ }: Options<State, EventMap>) {
55
+ const { stackRef } = React.useContext(NavigationBuilderContext);
56
+
57
+ // Cache object which holds navigation objects for each screen
58
+ // We use `React.useMemo` instead of `React.useRef` coz we want to invalidate it when deps change
59
+ // In reality, these deps will rarely change, if ever
60
+ const cache = React.useMemo(
61
+ () => ({ current: {} as NavigationCache<State, ScreenOptions, EventMap> }),
62
+ // eslint-disable-next-line react-hooks/exhaustive-deps
63
+ [getState, navigation, setOptions, router, emitter]
64
+ );
65
+
66
+ const actions = {
67
+ ...router.actionCreators,
68
+ ...CommonActions,
69
+ };
70
+
71
+ cache.current = state.routes.reduce<
72
+ NavigationCache<State, ScreenOptions, EventMap>
73
+ >((acc, route) => {
74
+ const previous = cache.current[route.key];
75
+
76
+ type Thunk =
77
+ | NavigationAction
78
+ | ((state: State) => NavigationAction | null | undefined);
79
+
80
+ if (previous) {
81
+ // If a cached navigation object already exists, reuse it
82
+ acc[route.key] = previous;
83
+ } else {
84
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
85
+ const { emit, ...rest } = navigation;
86
+
87
+ const dispatch = (thunk: Thunk) => {
88
+ const action = typeof thunk === 'function' ? thunk(getState()) : thunk;
89
+
90
+ if (action != null) {
91
+ navigation.dispatch({ source: route.key, ...action });
92
+ }
93
+ };
94
+
95
+ const withStack = (callback: () => void) => {
96
+ let isStackSet = false;
97
+
98
+ try {
99
+ if (
100
+ process.env.NODE_ENV !== 'production' &&
101
+ stackRef &&
102
+ !stackRef.current
103
+ ) {
104
+ // Capture the stack trace for devtools
105
+ stackRef.current = new Error().stack;
106
+ isStackSet = true;
107
+ }
108
+
109
+ callback();
110
+ } finally {
111
+ if (isStackSet && stackRef) {
112
+ stackRef.current = undefined;
113
+ }
114
+ }
115
+ };
116
+
117
+ const helpers = Object.keys(actions).reduce<Record<string, () => void>>(
118
+ (acc, name) => {
119
+ acc[name] = (...args: any) =>
120
+ withStack(() =>
121
+ // @ts-expect-error: name is a valid key, but TypeScript is dumb
122
+ dispatch(actions[name](...args))
123
+ );
124
+
125
+ return acc;
126
+ },
127
+ {}
128
+ );
129
+
130
+ acc[route.key] = {
131
+ ...rest,
132
+ ...helpers,
133
+ // FIXME: too much work to fix the types for now
134
+ ...(emitter.create(route.key) as any),
135
+ dispatch: (thunk: Thunk) => withStack(() => dispatch(thunk)),
136
+ setOptions: (options: object) =>
137
+ setOptions((o) => ({
138
+ ...o,
139
+ [route.key]: { ...o[route.key], ...options },
140
+ })),
141
+ isFocused: () => {
142
+ const state = getState();
143
+
144
+ if (state.routes[state.index].key !== route.key) {
145
+ return false;
146
+ }
147
+
148
+ // If the current screen is focused, we also need to check if parent navigator is focused
149
+ // This makes sure that we return the focus state in the whole tree, not just this navigator
150
+ return navigation ? navigation.isFocused() : true;
151
+ },
152
+ };
153
+ }
154
+
155
+ return acc;
156
+ }, {});
157
+
158
+ return cache.current;
159
+ }
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+
3
+ import createNavigationContainerRef from './createNavigationContainerRef';
4
+ import type { NavigationContainerRefWithCurrent } from './types';
5
+
6
+ export default function useNavigationContainerRef<
7
+ ParamList extends {} = ReactNavigation.RootParamList
8
+ >(): NavigationContainerRefWithCurrent<ParamList> {
9
+ const navigation =
10
+ React.useRef<NavigationContainerRefWithCurrent<ParamList> | null>(null);
11
+
12
+ if (navigation.current == null) {
13
+ navigation.current = createNavigationContainerRef<ParamList>();
14
+ }
15
+
16
+ return navigation.current;
17
+ }
@@ -0,0 +1,98 @@
1
+ import {
2
+ CommonActions,
3
+ NavigationAction,
4
+ NavigationState,
5
+ ParamListBase,
6
+ Router,
7
+ } from '@react-navigation/routers';
8
+ import * as React from 'react';
9
+
10
+ import NavigationContext from './NavigationContext';
11
+ import { NavigationHelpers, NavigationProp, PrivateValueStore } from './types';
12
+ import UnhandledActionContext from './UnhandledActionContext';
13
+ import type { NavigationEventEmitter } from './useEventEmitter';
14
+
15
+ // This is to make TypeScript compiler happy
16
+ // eslint-disable-next-line babel/no-unused-expressions
17
+ PrivateValueStore;
18
+
19
+ type Options<State extends NavigationState, Action extends NavigationAction> = {
20
+ onAction: (action: NavigationAction) => boolean;
21
+ getState: () => State;
22
+ emitter: NavigationEventEmitter<any>;
23
+ router: Router<State, Action>;
24
+ };
25
+
26
+ /**
27
+ * Navigation object with helper methods to be used by a navigator.
28
+ * This object includes methods for common actions as well as methods the parent screen's navigation object.
29
+ */
30
+ export default function useNavigationHelpers<
31
+ State extends NavigationState,
32
+ ActionHelpers extends Record<string, () => void>,
33
+ Action extends NavigationAction,
34
+ EventMap extends Record<string, any>
35
+ >({ onAction, getState, emitter, router }: Options<State, Action>) {
36
+ const onUnhandledAction = React.useContext(UnhandledActionContext);
37
+ const parentNavigationHelpers = React.useContext(NavigationContext);
38
+
39
+ return React.useMemo(() => {
40
+ const dispatch = (op: Action | ((state: State) => Action)) => {
41
+ const action = typeof op === 'function' ? op(getState()) : op;
42
+
43
+ const handled = onAction(action);
44
+
45
+ if (!handled) {
46
+ onUnhandledAction?.(action);
47
+ }
48
+ };
49
+
50
+ const actions = {
51
+ ...router.actionCreators,
52
+ ...CommonActions,
53
+ };
54
+
55
+ const helpers = Object.keys(actions).reduce<Record<string, () => void>>(
56
+ (acc, name) => {
57
+ // @ts-expect-error: name is a valid key, but TypeScript is dumb
58
+ acc[name] = (...args: any) => dispatch(actions[name](...args));
59
+ return acc;
60
+ },
61
+ {}
62
+ );
63
+
64
+ return {
65
+ ...parentNavigationHelpers,
66
+ ...helpers,
67
+ dispatch,
68
+ emit: emitter.emit,
69
+ isFocused: parentNavigationHelpers
70
+ ? parentNavigationHelpers.isFocused
71
+ : () => true,
72
+ canGoBack: () => {
73
+ const state = getState();
74
+
75
+ return (
76
+ router.getStateForAction(state, CommonActions.goBack() as Action, {
77
+ routeNames: state.routeNames,
78
+ routeParamList: {},
79
+ routeGetIdList: {},
80
+ }) !== null ||
81
+ parentNavigationHelpers?.canGoBack() ||
82
+ false
83
+ );
84
+ },
85
+ getParent: () => parentNavigationHelpers as any,
86
+ getState,
87
+ } as NavigationHelpers<ParamListBase, EventMap> &
88
+ (NavigationProp<ParamListBase, string, any, any, any> | undefined) &
89
+ ActionHelpers;
90
+ }, [
91
+ emitter.emit,
92
+ getState,
93
+ onAction,
94
+ onUnhandledAction,
95
+ parentNavigationHelpers,
96
+ router,
97
+ ]);
98
+ }
@@ -0,0 +1,41 @@
1
+ import type { NavigationState, ParamListBase } from '@react-navigation/routers';
2
+ import * as React from 'react';
3
+
4
+ import type { NavigationProp } from './types';
5
+ import useNavigation from './useNavigation';
6
+
7
+ type Selector<ParamList extends ParamListBase, T> = (
8
+ state: NavigationState<ParamList>
9
+ ) => T;
10
+
11
+ /**
12
+ * Hook to get a value from the current navigation state using a selector.
13
+ *
14
+ * @param selector Selector function to get a value from the state.
15
+ */
16
+ export default function useNavigationState<ParamList extends ParamListBase, T>(
17
+ selector: Selector<ParamList, T>
18
+ ): T {
19
+ const navigation = useNavigation<NavigationProp<ParamList>>();
20
+
21
+ // We don't care about the state value, we run the selector again at the end
22
+ // The state is only to make sure that there's a re-render when we have a new value
23
+ const [, setResult] = React.useState(() => selector(navigation.getState()));
24
+
25
+ // We store the selector in a ref to avoid re-subscribing listeners every render
26
+ const selectorRef = React.useRef(selector);
27
+
28
+ React.useEffect(() => {
29
+ selectorRef.current = selector;
30
+ });
31
+
32
+ React.useEffect(() => {
33
+ const unsubscribe = navigation.addListener('state', (e) => {
34
+ setResult(selectorRef.current(e.data.state));
35
+ });
36
+
37
+ return unsubscribe;
38
+ }, [navigation]);
39
+
40
+ return selector(navigation.getState());
41
+ }
@@ -0,0 +1,166 @@
1
+ import type {
2
+ NavigationAction,
3
+ NavigationState,
4
+ PartialState,
5
+ Router,
6
+ RouterConfigOptions,
7
+ } from '@react-navigation/routers';
8
+ import * as React from 'react';
9
+
10
+ import NavigationBuilderContext, {
11
+ ChildActionListener,
12
+ ChildBeforeRemoveListener,
13
+ } from './NavigationBuilderContext';
14
+ import type { EventMapCore } from './types';
15
+ import type { NavigationEventEmitter } from './useEventEmitter';
16
+ import useOnPreventRemove, { shouldPreventRemove } from './useOnPreventRemove';
17
+
18
+ type Options = {
19
+ router: Router<NavigationState, NavigationAction>;
20
+ key?: string;
21
+ getState: () => NavigationState;
22
+ setState: (state: NavigationState | PartialState<NavigationState>) => void;
23
+ actionListeners: ChildActionListener[];
24
+ beforeRemoveListeners: Record<string, ChildBeforeRemoveListener | undefined>;
25
+ routerConfigOptions: RouterConfigOptions;
26
+ emitter: NavigationEventEmitter<EventMapCore<any>>;
27
+ };
28
+
29
+ /**
30
+ * Hook to handle actions for a navigator, including state updates and bubbling.
31
+ *
32
+ * Bubbling an action is achieved in 2 ways:
33
+ * 1. To bubble action to parent, we expose the action handler in context and then access the parent context
34
+ * 2. To bubble action to child, child adds event listeners subscribing to actions from parent
35
+ *
36
+ * When the action handler handles as action, it returns `true`, otherwise `false`.
37
+ */
38
+ export default function useOnAction({
39
+ router,
40
+ getState,
41
+ setState,
42
+ key,
43
+ actionListeners,
44
+ beforeRemoveListeners,
45
+ routerConfigOptions,
46
+ emitter,
47
+ }: Options) {
48
+ const {
49
+ onAction: onActionParent,
50
+ onRouteFocus: onRouteFocusParent,
51
+ addListener: addListenerParent,
52
+ onDispatchAction,
53
+ } = React.useContext(NavigationBuilderContext);
54
+
55
+ const routerConfigOptionsRef =
56
+ React.useRef<RouterConfigOptions>(routerConfigOptions);
57
+
58
+ React.useEffect(() => {
59
+ routerConfigOptionsRef.current = routerConfigOptions;
60
+ });
61
+
62
+ const onAction = React.useCallback(
63
+ (
64
+ action: NavigationAction,
65
+ visitedNavigators: Set<string> = new Set<string>()
66
+ ) => {
67
+ const state = getState();
68
+
69
+ // Since actions can bubble both up and down, they could come to the same navigator again
70
+ // We keep track of navigators which have already tried to handle the action and return if it's already visited
71
+ if (visitedNavigators.has(state.key)) {
72
+ return false;
73
+ }
74
+
75
+ visitedNavigators.add(state.key);
76
+
77
+ if (typeof action.target !== 'string' || action.target === state.key) {
78
+ let result = router.getStateForAction(
79
+ state,
80
+ action,
81
+ routerConfigOptionsRef.current
82
+ );
83
+
84
+ // If a target is specified and set to current navigator, the action shouldn't bubble
85
+ // So instead of `null`, we use the state object for such cases to signal that action was handled
86
+ result =
87
+ result === null && action.target === state.key ? state : result;
88
+
89
+ if (result !== null) {
90
+ onDispatchAction(action, state === result);
91
+
92
+ if (state !== result) {
93
+ const isPrevented = shouldPreventRemove(
94
+ emitter,
95
+ beforeRemoveListeners,
96
+ state.routes,
97
+ result.routes,
98
+ action
99
+ );
100
+
101
+ if (isPrevented) {
102
+ return true;
103
+ }
104
+
105
+ setState(result);
106
+ }
107
+
108
+ if (onRouteFocusParent !== undefined) {
109
+ // Some actions such as `NAVIGATE` also want to bring the navigated route to focus in the whole tree
110
+ // This means we need to focus all of the parent navigators of this navigator as well
111
+ const shouldFocus = router.shouldActionChangeFocus(action);
112
+
113
+ if (shouldFocus && key !== undefined) {
114
+ onRouteFocusParent(key);
115
+ }
116
+ }
117
+
118
+ return true;
119
+ }
120
+ }
121
+
122
+ if (onActionParent !== undefined) {
123
+ // Bubble action to the parent if the current navigator didn't handle it
124
+ if (onActionParent(action, visitedNavigators)) {
125
+ return true;
126
+ }
127
+ }
128
+
129
+ // If the action wasn't handled by current navigator or a parent navigator, let children handle it
130
+ for (let i = actionListeners.length - 1; i >= 0; i--) {
131
+ const listener = actionListeners[i];
132
+
133
+ if (listener(action, visitedNavigators)) {
134
+ return true;
135
+ }
136
+ }
137
+
138
+ return false;
139
+ },
140
+ [
141
+ actionListeners,
142
+ beforeRemoveListeners,
143
+ emitter,
144
+ getState,
145
+ key,
146
+ onActionParent,
147
+ onDispatchAction,
148
+ onRouteFocusParent,
149
+ router,
150
+ setState,
151
+ ]
152
+ );
153
+
154
+ useOnPreventRemove({
155
+ getState,
156
+ emitter,
157
+ beforeRemoveListeners,
158
+ });
159
+
160
+ React.useEffect(
161
+ () => addListenerParent?.('action', onAction),
162
+ [addListenerParent, onAction]
163
+ );
164
+
165
+ return onAction;
166
+ }
@@ -0,0 +1,47 @@
1
+ import type { NavigationState } from '@react-navigation/routers';
2
+ import * as React from 'react';
3
+
4
+ import isArrayEqual from './isArrayEqual';
5
+ import NavigationBuilderContext, {
6
+ GetStateListener,
7
+ } from './NavigationBuilderContext';
8
+ import NavigationRouteContext from './NavigationRouteContext';
9
+
10
+ type Options = {
11
+ getState: () => NavigationState;
12
+ getStateListeners: Record<string, GetStateListener | undefined>;
13
+ };
14
+
15
+ export default function useOnGetState({
16
+ getState,
17
+ getStateListeners,
18
+ }: Options) {
19
+ const { addKeyedListener } = React.useContext(NavigationBuilderContext);
20
+ const route = React.useContext(NavigationRouteContext);
21
+ const key = route ? route.key : 'root';
22
+
23
+ const getRehydratedState = React.useCallback(() => {
24
+ const state = getState();
25
+
26
+ // Avoid returning new route objects if we don't need to
27
+ const routes = state.routes.map((route) => {
28
+ const childState = getStateListeners[route.key]?.();
29
+
30
+ if (route.state === childState) {
31
+ return route;
32
+ }
33
+
34
+ return { ...route, state: childState };
35
+ });
36
+
37
+ if (isArrayEqual(state.routes, routes)) {
38
+ return state;
39
+ }
40
+
41
+ return { ...state, routes };
42
+ }, [getState, getStateListeners]);
43
+
44
+ React.useEffect(() => {
45
+ return addKeyedListener?.('getState', key, getRehydratedState);
46
+ }, [addKeyedListener, getRehydratedState, key]);
47
+ }
@@ -0,0 +1,99 @@
1
+ import type {
2
+ NavigationAction,
3
+ NavigationState,
4
+ } from '@react-navigation/routers';
5
+ import * as React from 'react';
6
+
7
+ import NavigationBuilderContext, {
8
+ ChildBeforeRemoveListener,
9
+ } from './NavigationBuilderContext';
10
+ import NavigationRouteContext from './NavigationRouteContext';
11
+ import type { EventMapCore } from './types';
12
+ import type { NavigationEventEmitter } from './useEventEmitter';
13
+
14
+ type Options = {
15
+ getState: () => NavigationState;
16
+ emitter: NavigationEventEmitter<EventMapCore<any>>;
17
+ beforeRemoveListeners: Record<string, ChildBeforeRemoveListener | undefined>;
18
+ };
19
+
20
+ const VISITED_ROUTE_KEYS = Symbol('VISITED_ROUTE_KEYS');
21
+
22
+ export const shouldPreventRemove = (
23
+ emitter: NavigationEventEmitter<EventMapCore<any>>,
24
+ beforeRemoveListeners: Record<string, ChildBeforeRemoveListener | undefined>,
25
+ currentRoutes: { key: string }[],
26
+ nextRoutes: { key?: string | undefined }[],
27
+ action: NavigationAction
28
+ ) => {
29
+ const nextRouteKeys = nextRoutes.map((route) => route.key);
30
+
31
+ // Call these in reverse order so last screens handle the event first
32
+ const removedRoutes = currentRoutes
33
+ .filter((route) => !nextRouteKeys.includes(route.key))
34
+ .reverse();
35
+
36
+ const visitedRouteKeys: Set<string> =
37
+ // @ts-expect-error: add this property to mark that we've already emitted this action
38
+ action[VISITED_ROUTE_KEYS] ?? new Set<string>();
39
+
40
+ const beforeRemoveAction = {
41
+ ...action,
42
+ [VISITED_ROUTE_KEYS]: visitedRouteKeys,
43
+ };
44
+
45
+ for (const route of removedRoutes) {
46
+ if (visitedRouteKeys.has(route.key)) {
47
+ // Skip if we've already emitted this action for this screen
48
+ continue;
49
+ }
50
+
51
+ // First, we need to check if any child screens want to prevent it
52
+ const isPrevented = beforeRemoveListeners[route.key]?.(beforeRemoveAction);
53
+
54
+ if (isPrevented) {
55
+ return true;
56
+ }
57
+
58
+ visitedRouteKeys.add(route.key);
59
+
60
+ const event = emitter.emit({
61
+ type: 'beforeRemove',
62
+ target: route.key,
63
+ data: { action: beforeRemoveAction },
64
+ canPreventDefault: true,
65
+ });
66
+
67
+ if (event.defaultPrevented) {
68
+ return true;
69
+ }
70
+ }
71
+
72
+ return false;
73
+ };
74
+
75
+ export default function useOnPreventRemove({
76
+ getState,
77
+ emitter,
78
+ beforeRemoveListeners,
79
+ }: Options) {
80
+ const { addKeyedListener } = React.useContext(NavigationBuilderContext);
81
+ const route = React.useContext(NavigationRouteContext);
82
+ const routeKey = route?.key;
83
+
84
+ React.useEffect(() => {
85
+ if (routeKey) {
86
+ return addKeyedListener?.('beforeRemove', routeKey, (action) => {
87
+ const state = getState();
88
+
89
+ return shouldPreventRemove(
90
+ emitter,
91
+ beforeRemoveListeners,
92
+ state.routes,
93
+ [],
94
+ action
95
+ );
96
+ });
97
+ }
98
+ }, [addKeyedListener, beforeRemoveListeners, emitter, getState, routeKey]);
99
+ }
@@ -0,0 +1,47 @@
1
+ import type {
2
+ NavigationAction,
3
+ NavigationState,
4
+ Router,
5
+ } from '@react-navigation/routers';
6
+ import * as React from 'react';
7
+
8
+ import NavigationBuilderContext from './NavigationBuilderContext';
9
+
10
+ type Options<Action extends NavigationAction> = {
11
+ router: Router<NavigationState, Action>;
12
+ getState: () => NavigationState;
13
+ setState: (state: NavigationState) => void;
14
+ key?: string;
15
+ };
16
+
17
+ /**
18
+ * Hook to handle focus actions for a route.
19
+ * Focus action needs to be treated specially, coz when a nested route is focused,
20
+ * the parent navigators also needs to be focused.
21
+ */
22
+ export default function useOnRouteFocus<Action extends NavigationAction>({
23
+ router,
24
+ getState,
25
+ key: sourceRouteKey,
26
+ setState,
27
+ }: Options<Action>) {
28
+ const { onRouteFocus: onRouteFocusParent } = React.useContext(
29
+ NavigationBuilderContext
30
+ );
31
+
32
+ return React.useCallback(
33
+ (key: string) => {
34
+ const state = getState();
35
+ const result = router.getStateForRouteFocus(state, key);
36
+
37
+ if (result !== state) {
38
+ setState(result);
39
+ }
40
+
41
+ if (onRouteFocusParent !== undefined && sourceRouteKey !== undefined) {
42
+ onRouteFocusParent(sourceRouteKey);
43
+ }
44
+ },
45
+ [getState, onRouteFocusParent, router, setState, sourceRouteKey]
46
+ );
47
+ }