@react-navigation/core 8.0.0-alpha.3 → 8.0.0-alpha.30

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 (283) hide show
  1. package/lib/module/BaseNavigationContainer.js +34 -17
  2. package/lib/module/BaseNavigationContainer.js.map +1 -1
  3. package/lib/module/ConsumedParamsContext.js +5 -0
  4. package/lib/module/ConsumedParamsContext.js.map +1 -0
  5. package/lib/module/DataLoading.js +127 -0
  6. package/lib/module/DataLoading.js.map +1 -0
  7. package/lib/module/NavigationBuilderContext.js +1 -0
  8. package/lib/module/NavigationBuilderContext.js.map +1 -1
  9. package/lib/module/NavigationIndependentTree.js +17 -8
  10. package/lib/module/NavigationIndependentTree.js.map +1 -1
  11. package/lib/module/NavigationProvider.js +22 -11
  12. package/lib/module/NavigationProvider.js.map +1 -1
  13. package/lib/module/NavigationStateContext.js.map +1 -1
  14. package/lib/module/PreventRemoveContext.js.map +1 -1
  15. package/lib/module/PreventRemoveProvider.js +37 -27
  16. package/lib/module/PreventRemoveProvider.js.map +1 -1
  17. package/lib/module/SceneView.js +7 -40
  18. package/lib/module/SceneView.js.map +1 -1
  19. package/lib/module/StaticNavigation.js +179 -50
  20. package/lib/module/StaticNavigation.js.map +1 -1
  21. package/lib/module/StaticTreeContext.js +5 -0
  22. package/lib/module/StaticTreeContext.js.map +1 -0
  23. package/lib/module/checkSerializable.js +18 -13
  24. package/lib/module/checkSerializable.js.map +1 -1
  25. package/lib/module/createNavigationContainerRef.js +6 -8
  26. package/lib/module/createNavigationContainerRef.js.map +1 -1
  27. package/lib/module/createNavigatorFactory.js +27 -5
  28. package/lib/module/createNavigatorFactory.js.map +1 -1
  29. package/lib/module/findFocusedRoute.js +7 -4
  30. package/lib/module/findFocusedRoute.js.map +1 -1
  31. package/lib/module/getActionFromState.js +45 -20
  32. package/lib/module/getActionFromState.js.map +1 -1
  33. package/lib/module/getPathFromState.js +171 -90
  34. package/lib/module/getPathFromState.js.map +1 -1
  35. package/lib/module/getPatternParts.js +20 -4
  36. package/lib/module/getPatternParts.js.map +1 -1
  37. package/lib/module/getStateFromPath.js +485 -214
  38. package/lib/module/getStateFromPath.js.map +1 -1
  39. package/lib/module/getStateFromRouteParams.js +24 -0
  40. package/lib/module/getStateFromRouteParams.js.map +1 -0
  41. package/lib/module/index.js +5 -4
  42. package/lib/module/index.js.map +1 -1
  43. package/lib/module/theming/useTheme.js +1 -1
  44. package/lib/module/theming/useTheme.js.map +1 -1
  45. package/lib/module/types.js +35 -0
  46. package/lib/module/types.js.map +1 -1
  47. package/lib/module/useDescriptors.js +19 -11
  48. package/lib/module/useDescriptors.js.map +1 -1
  49. package/lib/module/useEventEmitter.js +48 -33
  50. package/lib/module/useEventEmitter.js.map +1 -1
  51. package/lib/module/useFocusEvents.js +12 -4
  52. package/lib/module/useFocusEvents.js.map +1 -1
  53. package/lib/module/useFocusedListenersChildrenAdapter.js +2 -2
  54. package/lib/module/useFocusedListenersChildrenAdapter.js.map +1 -1
  55. package/lib/module/useIsFocused.js +7 -12
  56. package/lib/module/useIsFocused.js.map +1 -1
  57. package/lib/module/useKeyedChildListeners.js +4 -2
  58. package/lib/module/useKeyedChildListeners.js.map +1 -1
  59. package/lib/module/useLazyValue.js.map +1 -1
  60. package/lib/module/useNavigation.js +2 -15
  61. package/lib/module/useNavigation.js.map +1 -1
  62. package/lib/module/useNavigationBuilder.js +201 -131
  63. package/lib/module/useNavigationBuilder.js.map +1 -1
  64. package/lib/module/useNavigationCache.js +22 -17
  65. package/lib/module/useNavigationCache.js.map +1 -1
  66. package/lib/module/useNavigationHelpers.js +28 -10
  67. package/lib/module/useNavigationHelpers.js.map +1 -1
  68. package/lib/module/useNavigationIndependentTree.js +1 -1
  69. package/lib/module/useNavigationIndependentTree.js.map +1 -1
  70. package/lib/module/useNavigationState.js +70 -35
  71. package/lib/module/useNavigationState.js.map +1 -1
  72. package/lib/module/useOnAction.js +37 -7
  73. package/lib/module/useOnAction.js.map +1 -1
  74. package/lib/module/useOnGetState.js +6 -3
  75. package/lib/module/useOnGetState.js.map +1 -1
  76. package/lib/module/useOnPreventRemove.js +39 -30
  77. package/lib/module/useOnPreventRemove.js.map +1 -1
  78. package/lib/module/useOnRouteFocus.js +1 -1
  79. package/lib/module/useOnRouteFocus.js.map +1 -1
  80. package/lib/module/useOptionsGetters.js +10 -5
  81. package/lib/module/useOptionsGetters.js.map +1 -1
  82. package/lib/module/usePreventRemove.js +10 -3
  83. package/lib/module/usePreventRemove.js.map +1 -1
  84. package/lib/module/usePreventRemoveContext.js +1 -1
  85. package/lib/module/usePreventRemoveContext.js.map +1 -1
  86. package/lib/module/useRegisterNavigator.js +2 -2
  87. package/lib/module/useRegisterNavigator.js.map +1 -1
  88. package/lib/module/useRoute.js +2 -0
  89. package/lib/module/useRoute.js.map +1 -1
  90. package/lib/module/useRouteCache.js +17 -11
  91. package/lib/module/useRouteCache.js.map +1 -1
  92. package/lib/module/useScheduleUpdate.js +9 -9
  93. package/lib/module/useScheduleUpdate.js.map +1 -1
  94. package/lib/module/useStateForPath.js +1 -1
  95. package/lib/module/useStateForPath.js.map +1 -1
  96. package/lib/module/useSyncState.js +7 -3
  97. package/lib/module/useSyncState.js.map +1 -1
  98. package/lib/module/validatePathConfig.js +50 -36
  99. package/lib/module/validatePathConfig.js.map +1 -1
  100. package/lib/typescript/src/BaseNavigationContainer.d.ts +6 -3
  101. package/lib/typescript/src/BaseNavigationContainer.d.ts.map +1 -1
  102. package/lib/typescript/src/ConsumedParamsContext.d.ts +3 -0
  103. package/lib/typescript/src/ConsumedParamsContext.d.ts.map +1 -0
  104. package/lib/typescript/src/DataLoading.d.ts +21 -0
  105. package/lib/typescript/src/DataLoading.d.ts.map +1 -0
  106. package/lib/typescript/src/EnsureSingleNavigator.d.ts +1 -1
  107. package/lib/typescript/src/EnsureSingleNavigator.d.ts.map +1 -1
  108. package/lib/typescript/src/Group.d.ts +1 -1
  109. package/lib/typescript/src/Group.d.ts.map +1 -1
  110. package/lib/typescript/src/NavigationBuilderContext.d.ts +9 -8
  111. package/lib/typescript/src/NavigationBuilderContext.d.ts.map +1 -1
  112. package/lib/typescript/src/NavigationContainerRefContext.d.ts +1 -1
  113. package/lib/typescript/src/NavigationContainerRefContext.d.ts.map +1 -1
  114. package/lib/typescript/src/NavigationFocusedRouteStateContext.d.ts +4 -4
  115. package/lib/typescript/src/NavigationFocusedRouteStateContext.d.ts.map +1 -1
  116. package/lib/typescript/src/NavigationHelpersContext.d.ts +1 -1
  117. package/lib/typescript/src/NavigationHelpersContext.d.ts.map +1 -1
  118. package/lib/typescript/src/NavigationIndependentTree.d.ts +1 -1
  119. package/lib/typescript/src/NavigationIndependentTree.d.ts.map +1 -1
  120. package/lib/typescript/src/NavigationProvider.d.ts +12 -13
  121. package/lib/typescript/src/NavigationProvider.d.ts.map +1 -1
  122. package/lib/typescript/src/NavigationStateContext.d.ts +3 -3
  123. package/lib/typescript/src/NavigationStateContext.d.ts.map +1 -1
  124. package/lib/typescript/src/PreventRemoveContext.d.ts +1 -0
  125. package/lib/typescript/src/PreventRemoveContext.d.ts.map +1 -1
  126. package/lib/typescript/src/PreventRemoveProvider.d.ts +1 -1
  127. package/lib/typescript/src/PreventRemoveProvider.d.ts.map +1 -1
  128. package/lib/typescript/src/SceneView.d.ts +3 -2
  129. package/lib/typescript/src/SceneView.d.ts.map +1 -1
  130. package/lib/typescript/src/Screen.d.ts +1 -1
  131. package/lib/typescript/src/Screen.d.ts.map +1 -1
  132. package/lib/typescript/src/StaticContainer.d.ts +1 -1
  133. package/lib/typescript/src/StaticContainer.d.ts.map +1 -1
  134. package/lib/typescript/src/StaticNavigation.d.ts +189 -109
  135. package/lib/typescript/src/StaticNavigation.d.ts.map +1 -1
  136. package/lib/typescript/src/StaticTreeContext.d.ts +4 -0
  137. package/lib/typescript/src/StaticTreeContext.d.ts.map +1 -0
  138. package/lib/typescript/src/checkSerializable.d.ts +8 -4
  139. package/lib/typescript/src/checkSerializable.d.ts.map +1 -1
  140. package/lib/typescript/src/createNavigationContainerRef.d.ts +1 -1
  141. package/lib/typescript/src/createNavigationContainerRef.d.ts.map +1 -1
  142. package/lib/typescript/src/createNavigatorFactory.d.ts +23 -5
  143. package/lib/typescript/src/createNavigatorFactory.d.ts.map +1 -1
  144. package/lib/typescript/src/findFocusedRoute.d.ts +3 -3
  145. package/lib/typescript/src/findFocusedRoute.d.ts.map +1 -1
  146. package/lib/typescript/src/getActionFromState.d.ts +4 -4
  147. package/lib/typescript/src/getActionFromState.d.ts.map +1 -1
  148. package/lib/typescript/src/getPathFromState.d.ts +3 -3
  149. package/lib/typescript/src/getPathFromState.d.ts.map +1 -1
  150. package/lib/typescript/src/getPatternParts.d.ts +1 -0
  151. package/lib/typescript/src/getPatternParts.d.ts.map +1 -1
  152. package/lib/typescript/src/getStateFromPath.d.ts +5 -5
  153. package/lib/typescript/src/getStateFromPath.d.ts.map +1 -1
  154. package/lib/typescript/src/getStateFromRouteParams.d.ts +3 -0
  155. package/lib/typescript/src/getStateFromRouteParams.d.ts.map +1 -0
  156. package/lib/typescript/src/index.d.ts +36 -33
  157. package/lib/typescript/src/index.d.ts.map +1 -1
  158. package/lib/typescript/src/theming/ThemeContext.d.ts +1 -1
  159. package/lib/typescript/src/theming/ThemeContext.d.ts.map +1 -1
  160. package/lib/typescript/src/theming/ThemeProvider.d.ts +2 -2
  161. package/lib/typescript/src/theming/ThemeProvider.d.ts.map +1 -1
  162. package/lib/typescript/src/theming/useTheme.d.ts +1 -1
  163. package/lib/typescript/src/theming/useTheme.d.ts.map +1 -1
  164. package/lib/typescript/src/types.d.ts +260 -159
  165. package/lib/typescript/src/types.d.ts.map +1 -1
  166. package/lib/typescript/src/useChildListeners.d.ts +3 -3
  167. package/lib/typescript/src/useChildListeners.d.ts.map +1 -1
  168. package/lib/typescript/src/useComponent.d.ts +1 -1
  169. package/lib/typescript/src/useComponent.d.ts.map +1 -1
  170. package/lib/typescript/src/useDescriptors.d.ts +8 -8
  171. package/lib/typescript/src/useDescriptors.d.ts.map +1 -1
  172. package/lib/typescript/src/useEventEmitter.d.ts +2 -2
  173. package/lib/typescript/src/useEventEmitter.d.ts.map +1 -1
  174. package/lib/typescript/src/useFocusEvents.d.ts +2 -2
  175. package/lib/typescript/src/useFocusEvents.d.ts.map +1 -1
  176. package/lib/typescript/src/useFocusedListenersChildrenAdapter.d.ts +2 -2
  177. package/lib/typescript/src/useFocusedListenersChildrenAdapter.d.ts.map +1 -1
  178. package/lib/typescript/src/useIsFocused.d.ts +3 -0
  179. package/lib/typescript/src/useIsFocused.d.ts.map +1 -1
  180. package/lib/typescript/src/useKeyedChildListeners.d.ts +3 -3
  181. package/lib/typescript/src/useKeyedChildListeners.d.ts.map +1 -1
  182. package/lib/typescript/src/useLazyValue.d.ts.map +1 -1
  183. package/lib/typescript/src/useNavigation.d.ts +4 -2
  184. package/lib/typescript/src/useNavigation.d.ts.map +1 -1
  185. package/lib/typescript/src/useNavigationBuilder.d.ts +23 -30
  186. package/lib/typescript/src/useNavigationBuilder.d.ts.map +1 -1
  187. package/lib/typescript/src/useNavigationCache.d.ts +3 -3
  188. package/lib/typescript/src/useNavigationCache.d.ts.map +1 -1
  189. package/lib/typescript/src/useNavigationContainerRef.d.ts +1 -1
  190. package/lib/typescript/src/useNavigationContainerRef.d.ts.map +1 -1
  191. package/lib/typescript/src/useNavigationHelpers.d.ts +19 -27
  192. package/lib/typescript/src/useNavigationHelpers.d.ts.map +1 -1
  193. package/lib/typescript/src/useNavigationState.d.ts +13 -3
  194. package/lib/typescript/src/useNavigationState.d.ts.map +1 -1
  195. package/lib/typescript/src/useOnAction.d.ts +9 -9
  196. package/lib/typescript/src/useOnAction.d.ts.map +1 -1
  197. package/lib/typescript/src/useOnGetState.d.ts +1 -1
  198. package/lib/typescript/src/useOnGetState.d.ts.map +1 -1
  199. package/lib/typescript/src/useOnPreventRemove.d.ts +5 -9
  200. package/lib/typescript/src/useOnPreventRemove.d.ts.map +1 -1
  201. package/lib/typescript/src/useOnRouteFocus.d.ts +6 -6
  202. package/lib/typescript/src/useOnRouteFocus.d.ts.map +1 -1
  203. package/lib/typescript/src/useOptionsGetters.d.ts +1 -1
  204. package/lib/typescript/src/useOptionsGetters.d.ts.map +1 -1
  205. package/lib/typescript/src/usePreventRemove.d.ts.map +1 -1
  206. package/lib/typescript/src/usePreventRemoveContext.d.ts +2 -1
  207. package/lib/typescript/src/usePreventRemoveContext.d.ts.map +1 -1
  208. package/lib/typescript/src/useRoute.d.ts +7 -3
  209. package/lib/typescript/src/useRoute.d.ts.map +1 -1
  210. package/lib/typescript/src/useRouteCache.d.ts +5 -5
  211. package/lib/typescript/src/useRouteCache.d.ts.map +1 -1
  212. package/lib/typescript/src/useScheduleUpdate.d.ts +5 -4
  213. package/lib/typescript/src/useScheduleUpdate.d.ts.map +1 -1
  214. package/lib/typescript/src/useStateForPath.d.ts +1 -1
  215. package/lib/typescript/src/useStateForPath.d.ts.map +1 -1
  216. package/lib/typescript/src/useSyncState.d.ts.map +1 -1
  217. package/lib/typescript/src/utilities.d.ts +74 -37
  218. package/lib/typescript/src/utilities.d.ts.map +1 -1
  219. package/lib/typescript/src/validatePathConfig.d.ts.map +1 -1
  220. package/package.json +23 -22
  221. package/src/BaseNavigationContainer.tsx +351 -333
  222. package/src/ConsumedParamsContext.tsx +5 -0
  223. package/src/DataLoading.tsx +203 -0
  224. package/src/NavigationBuilderContext.tsx +14 -9
  225. package/src/NavigationFocusedRouteStateContext.tsx +4 -4
  226. package/src/NavigationIndependentTree.tsx +18 -12
  227. package/src/NavigationProvider.tsx +26 -15
  228. package/src/NavigationStateContext.tsx +5 -6
  229. package/src/PreventRemoveContext.tsx +1 -0
  230. package/src/PreventRemoveProvider.tsx +51 -46
  231. package/src/SceneView.tsx +7 -39
  232. package/src/StaticNavigation.tsx +659 -307
  233. package/src/StaticTreeContext.tsx +7 -0
  234. package/src/checkSerializable.tsx +35 -19
  235. package/src/createNavigationContainerRef.tsx +12 -9
  236. package/src/createNavigatorFactory.tsx +92 -8
  237. package/src/findFocusedRoute.tsx +13 -8
  238. package/src/getActionFromState.tsx +86 -51
  239. package/src/getPathFromState.tsx +254 -128
  240. package/src/getPatternParts.tsx +25 -4
  241. package/src/getStateFromPath.tsx +811 -309
  242. package/src/getStateFromRouteParams.tsx +60 -0
  243. package/src/index.tsx +55 -5
  244. package/src/theming/useTheme.tsx +1 -1
  245. package/src/types.tsx +798 -373
  246. package/src/useDescriptors.tsx +28 -14
  247. package/src/useEventEmitter.tsx +52 -38
  248. package/src/useFocusEvents.tsx +15 -7
  249. package/src/useFocusedListenersChildrenAdapter.tsx +2 -2
  250. package/src/useIsFocused.tsx +14 -21
  251. package/src/useKeyedChildListeners.tsx +4 -2
  252. package/src/useLazyValue.tsx +2 -2
  253. package/src/useNavigation.tsx +7 -24
  254. package/src/useNavigationBuilder.tsx +311 -186
  255. package/src/useNavigationCache.tsx +32 -25
  256. package/src/useNavigationHelpers.tsx +27 -10
  257. package/src/useNavigationIndependentTree.tsx +1 -1
  258. package/src/useNavigationState.tsx +93 -59
  259. package/src/useOnAction.tsx +61 -13
  260. package/src/useOnGetState.tsx +5 -3
  261. package/src/useOnPreventRemove.tsx +75 -42
  262. package/src/useOnRouteFocus.tsx +10 -12
  263. package/src/useOptionsGetters.tsx +11 -5
  264. package/src/usePreventRemove.tsx +12 -3
  265. package/src/usePreventRemoveContext.tsx +1 -1
  266. package/src/useRegisterNavigator.tsx +2 -2
  267. package/src/useRoute.tsx +20 -6
  268. package/src/useRouteCache.tsx +22 -16
  269. package/src/useScheduleUpdate.tsx +9 -10
  270. package/src/useStateForPath.tsx +1 -1
  271. package/src/useSyncState.tsx +8 -3
  272. package/src/utilities.tsx +144 -31
  273. package/src/validatePathConfig.tsx +86 -57
  274. package/lib/module/CurrentRenderContext.js +0 -10
  275. package/lib/module/CurrentRenderContext.js.map +0 -1
  276. package/lib/module/useCurrentRender.js +0 -19
  277. package/lib/module/useCurrentRender.js.map +0 -1
  278. package/lib/typescript/src/CurrentRenderContext.d.ts +0 -9
  279. package/lib/typescript/src/CurrentRenderContext.d.ts.map +0 -1
  280. package/lib/typescript/src/useCurrentRender.d.ts +0 -14
  281. package/lib/typescript/src/useCurrentRender.d.ts.map +0 -1
  282. package/src/CurrentRenderContext.tsx +0 -9
  283. package/src/useCurrentRender.tsx +0 -31
@@ -3,7 +3,6 @@ import {
3
3
  type InitialState,
4
4
  type NavigationAction,
5
5
  type NavigationState,
6
- type ParamListBase,
7
6
  type PartialState,
8
7
  type Route,
9
8
  } from '@react-navigation/routers';
@@ -12,6 +11,7 @@ import useLatestCallback from 'use-latest-callback';
12
11
 
13
12
  import { checkDuplicateRouteNames } from './checkDuplicateRouteNames';
14
13
  import { checkSerializable } from './checkSerializable';
14
+ import { ConsumedParamsContext } from './ConsumedParamsContext';
15
15
  import { NOT_INITIALIZED_ERROR } from './createNavigationContainerRef';
16
16
  import { EnsureSingleNavigator } from './EnsureSingleNavigator';
17
17
  import { findFocusedRoute } from './findFocusedRoute';
@@ -24,11 +24,13 @@ import type {
24
24
  NavigationContainerEventMap,
25
25
  NavigationContainerProps,
26
26
  NavigationContainerRef,
27
+ RootParamList,
27
28
  } from './types';
28
29
  import { UnhandledActionContext } from './UnhandledActionContext';
29
30
  import { useChildListeners } from './useChildListeners';
30
31
  import { useEventEmitter } from './useEventEmitter';
31
32
  import { useKeyedChildListeners } from './useKeyedChildListeners';
33
+ import { useLazyValue } from './useLazyValue';
32
34
  import { useNavigationIndependentTree } from './useNavigationIndependentTree';
33
35
  import { useOptionsGetters } from './useOptionsGetters';
34
36
  import { useSyncState } from './useSyncState';
@@ -38,6 +40,10 @@ type State = NavigationState | PartialState<NavigationState> | undefined;
38
40
  const serializableWarnings: string[] = [];
39
41
  const duplicateNameWarnings: string[] = [];
40
42
 
43
+ type Props<ParamList extends {}> = NavigationContainerProps & {
44
+ ref?: React.Ref<NavigationContainerRef<ParamList>>;
45
+ };
46
+
41
47
  /**
42
48
  * Remove `key` and `routeNames` from the state objects recursively to get partial state.
43
49
  *
@@ -80,387 +86,399 @@ const getPartialState = (
80
86
  * @param props.children Child elements to render the content.
81
87
  * @param props.ref Ref object which refers to the navigation object containing helper methods.
82
88
  */
83
- export const BaseNavigationContainer = React.forwardRef(
84
- function BaseNavigationContainer(
85
- {
86
- initialState,
87
- onStateChange,
88
- onReady,
89
- onUnhandledAction,
90
- theme,
91
- children,
92
- }: NavigationContainerProps,
93
- ref?: React.Ref<NavigationContainerRef<ParamListBase>>
94
- ) {
95
- const parent = React.useContext(NavigationStateContext);
96
- const independent = useNavigationIndependentTree();
97
-
98
- if (!parent.isDefault && !independent) {
99
- throw new Error(
100
- "Looks like you have nested a 'NavigationContainer' inside another. Normally you need only one container at the root of the app, so this was probably an error. If this was intentional, wrap the container in 'NavigationIndependentTree' explicitly. Note that this will make the child navigators disconnected from the parent and you won't be able to navigate between them."
101
- );
102
- }
89
+ export function BaseNavigationContainer<ParamList extends {} = RootParamList>({
90
+ initialState,
91
+ onStateChange,
92
+ onReady,
93
+ onUnhandledAction,
94
+ theme,
95
+ children,
96
+ ref,
97
+ }: Props<ParamList>) {
98
+ const parent = React.use(NavigationStateContext);
99
+ const independent = useNavigationIndependentTree();
100
+
101
+ if (!parent.isDefault && !independent) {
102
+ throw new Error(
103
+ "Looks like you have nested a 'NavigationContainer' inside another. Normally you need only one container at the root of the app, so this was probably an error. If this was intentional, wrap the container in 'NavigationIndependentTree' explicitly. Note that this will make the child navigators disconnected from the parent and you won't be able to navigate between them."
104
+ );
105
+ }
103
106
 
104
- const { state, getState, setState, scheduleUpdate, flushUpdates } =
105
- useSyncState<State>(() =>
106
- getPartialState(initialState == null ? undefined : initialState)
107
- );
107
+ const { state, getState, setState, scheduleUpdate, flushUpdates } =
108
+ useSyncState<State>(() =>
109
+ getPartialState(initialState == null ? undefined : initialState)
110
+ );
108
111
 
109
- const isFirstMountRef = React.useRef<boolean>(true);
112
+ const consumedParams = useLazyValue(() => new WeakMap<object, true>());
110
113
 
111
- const navigatorKeyRef = React.useRef<string | undefined>(undefined);
114
+ const isFirstMountRef = React.useRef<boolean>(true);
112
115
 
113
- const getKey = React.useCallback(() => navigatorKeyRef.current, []);
116
+ const navigatorKeyRef = React.useRef<string | undefined>(undefined);
114
117
 
115
- const setKey = React.useCallback((key: string) => {
116
- navigatorKeyRef.current = key;
117
- }, []);
118
+ const getKey = React.useCallback(() => navigatorKeyRef.current, []);
118
119
 
119
- const { listeners, addListener } = useChildListeners();
120
+ const setKey = React.useCallback((key: string) => {
121
+ navigatorKeyRef.current = key;
122
+ }, []);
120
123
 
121
- const { keyedListeners, addKeyedListener } = useKeyedChildListeners();
124
+ const { listeners, addListener } = useChildListeners();
122
125
 
123
- const dispatch = useLatestCallback(
124
- (
125
- action:
126
- | NavigationAction
127
- | ((state: NavigationState) => NavigationAction)
128
- ) => {
129
- if (listeners.focus[0] == null) {
130
- console.error(NOT_INITIALIZED_ERROR);
131
- } else {
132
- listeners.focus[0]((navigation) => navigation.dispatch(action));
133
- }
126
+ const { keyedListeners, addKeyedListener } = useKeyedChildListeners();
127
+
128
+ const dispatch = useLatestCallback(
129
+ (
130
+ action: NavigationAction | ((state: NavigationState) => NavigationAction)
131
+ ) => {
132
+ const listener = listeners.focus[0];
133
+
134
+ if (listener == null) {
135
+ console.error(NOT_INITIALIZED_ERROR);
136
+ } else {
137
+ listener((navigation) =>
138
+ React.startTransition(() => {
139
+ navigation.dispatch(action);
140
+ })
141
+ );
134
142
  }
143
+ }
144
+ );
145
+
146
+ const canGoBack = useLatestCallback(() => {
147
+ if (listeners.focus[0] == null) {
148
+ return false;
149
+ }
150
+
151
+ const { result, handled } = listeners.focus[0]((navigation) =>
152
+ navigation.canGoBack()
135
153
  );
136
154
 
137
- const canGoBack = useLatestCallback(() => {
138
- if (listeners.focus[0] == null) {
139
- return false;
140
- }
155
+ if (handled) {
156
+ return result;
157
+ } else {
158
+ return false;
159
+ }
160
+ });
141
161
 
142
- const { result, handled } = listeners.focus[0]((navigation) =>
143
- navigation.canGoBack()
144
- );
162
+ const resetRoot = useLatestCallback(
163
+ (state: PartialState<NavigationState> | NavigationState) => {
164
+ const target = state?.key ?? keyedListeners.getState.root?.().key;
165
+ const listener = listeners.focus[0];
145
166
 
146
- if (handled) {
147
- return result;
167
+ if (target == null || listener == null) {
168
+ console.error(NOT_INITIALIZED_ERROR);
148
169
  } else {
149
- return false;
170
+ listener((navigation) =>
171
+ navigation.dispatch({
172
+ ...CommonActions.reset(state),
173
+ target,
174
+ })
175
+ );
150
176
  }
151
- });
177
+ }
178
+ );
152
179
 
153
- const resetRoot = useLatestCallback(
154
- (state?: PartialState<NavigationState> | NavigationState) => {
155
- const target = state?.key ?? keyedListeners.getState.root?.().key;
156
-
157
- if (target == null) {
158
- console.error(NOT_INITIALIZED_ERROR);
159
- } else {
160
- listeners.focus[0]((navigation) =>
161
- navigation.dispatch({
162
- ...CommonActions.reset(state),
163
- target,
164
- })
165
- );
166
- }
167
- }
168
- );
180
+ const getRootState = useLatestCallback(() => {
181
+ return keyedListeners.getState.root?.();
182
+ });
169
183
 
170
- const getRootState = useLatestCallback(() => {
171
- return keyedListeners.getState.root?.();
172
- });
184
+ const getCurrentRoute = useLatestCallback(() => {
185
+ const state = getRootState();
173
186
 
174
- const getCurrentRoute = useLatestCallback(() => {
175
- const state = getRootState();
187
+ if (state == null) {
188
+ return undefined;
189
+ }
176
190
 
177
- if (state == null) {
178
- return undefined;
179
- }
191
+ const route = findFocusedRoute(state);
192
+
193
+ return route as Route<string> | undefined;
194
+ });
195
+
196
+ const isReady = useLatestCallback(() => listeners.focus[0] != null);
197
+
198
+ const emitter = useEventEmitter<NavigationContainerEventMap>();
199
+
200
+ const { addOptionsGetter, getCurrentOptions } = useOptionsGetters({});
201
+
202
+ const navigation: NavigationContainerRef<ParamList> = React.useMemo(
203
+ () => ({
204
+ ...Object.keys(CommonActions).reduce<any>((acc, name) => {
205
+ acc[name] = (...args: any[]) =>
206
+ // @ts-expect-error: this is ok
207
+ dispatch(CommonActions[name](...args));
208
+
209
+ return acc;
210
+ }, {}),
211
+ ...emitter.create('root'),
212
+ dispatch,
213
+ resetRoot,
214
+ isFocused: () => true,
215
+ canGoBack,
216
+ getParent: () => undefined,
217
+ getState,
218
+ getRootState,
219
+ getCurrentRoute,
220
+ getCurrentOptions,
221
+ isReady,
222
+ setOptions: () => {
223
+ throw new Error('Cannot call setOptions outside a screen');
224
+ },
225
+ }),
226
+ [
227
+ canGoBack,
228
+ dispatch,
229
+ emitter,
230
+ getCurrentOptions,
231
+ getCurrentRoute,
232
+ getRootState,
233
+ getState,
234
+ isReady,
235
+ resetRoot,
236
+ ]
237
+ );
238
+
239
+ React.useImperativeHandle(ref, () => navigation, [navigation]);
240
+
241
+ const onDispatchAction = useLatestCallback(
242
+ (action: NavigationAction, noop: boolean) => {
243
+ emitter.emit({
244
+ type: '__unsafe_action__',
245
+ data: { action, noop, stack: stackRef.current },
246
+ });
247
+ }
248
+ );
249
+
250
+ const onEmitEvent = useLatestCallback(
251
+ (event: {
252
+ type: string;
253
+ defaultPrevented: boolean | undefined;
254
+ target: string | undefined;
255
+ data: unknown;
256
+ }) => {
257
+ emitter.emit({
258
+ type: '__unsafe_event__',
259
+ data: event,
260
+ });
261
+ }
262
+ );
180
263
 
181
- const route = findFocusedRoute(state);
264
+ const lastEmittedOptionsRef = React.useRef<object | undefined>(undefined);
182
265
 
183
- return route as Route<string> | undefined;
184
- });
266
+ const onOptionsChange = useLatestCallback((options: object) => {
267
+ if (lastEmittedOptionsRef.current === options) {
268
+ return;
269
+ }
185
270
 
186
- const isReady = useLatestCallback(() => listeners.focus[0] != null);
187
-
188
- const emitter = useEventEmitter<NavigationContainerEventMap>();
189
-
190
- const { addOptionsGetter, getCurrentOptions } = useOptionsGetters({});
191
-
192
- const navigation: NavigationContainerRef<ParamListBase> = React.useMemo(
193
- () => ({
194
- ...Object.keys(CommonActions).reduce<any>((acc, name) => {
195
- acc[name] = (...args: any[]) =>
196
- // @ts-expect-error: this is ok
197
- dispatch(CommonActions[name](...args));
198
- return acc;
199
- }, {}),
200
- ...emitter.create('root'),
201
- dispatch,
202
- resetRoot,
203
- isFocused: () => true,
204
- canGoBack,
205
- getParent: () => undefined,
206
- getState,
207
- getRootState,
208
- getCurrentRoute,
209
- getCurrentOptions,
210
- isReady,
211
- setOptions: () => {
212
- throw new Error('Cannot call setOptions outside a screen');
213
- },
214
- }),
215
- [
216
- canGoBack,
217
- dispatch,
218
- emitter,
219
- getCurrentOptions,
220
- getCurrentRoute,
221
- getRootState,
222
- getState,
223
- isReady,
224
- resetRoot,
225
- ]
226
- );
271
+ lastEmittedOptionsRef.current = options;
227
272
 
228
- React.useImperativeHandle(ref, () => navigation, [navigation]);
273
+ emitter.emit({
274
+ type: 'options',
275
+ data: { options },
276
+ });
277
+ });
278
+
279
+ const stackRef = React.useRef<string | undefined>(undefined);
280
+
281
+ const lastEmittedStateRef = React.useRef<State>(undefined);
282
+
283
+ const getIsStateEmitted = useLatestCallback(
284
+ () => !isFirstMountRef.current && lastEmittedStateRef.current === getState()
285
+ );
286
+
287
+ const builderContext = React.useMemo(
288
+ () => ({
289
+ addListener,
290
+ addKeyedListener,
291
+ onDispatchAction,
292
+ onEmitEvent,
293
+ onOptionsChange,
294
+ getIsStateEmitted,
295
+ scheduleUpdate,
296
+ flushUpdates,
297
+ stackRef,
298
+ }),
299
+ [
300
+ addListener,
301
+ addKeyedListener,
302
+ onDispatchAction,
303
+ onEmitEvent,
304
+ onOptionsChange,
305
+ getIsStateEmitted,
306
+ scheduleUpdate,
307
+ flushUpdates,
308
+ ]
309
+ );
310
+
311
+ const isInitialRef = React.useRef(true);
312
+
313
+ const getIsInitial = React.useCallback(() => isInitialRef.current, []);
314
+
315
+ const context = React.useMemo(
316
+ () => ({
317
+ state,
318
+ getState,
319
+ setState,
320
+ getKey,
321
+ setKey,
322
+ getIsInitial,
323
+ addOptionsGetter,
324
+ }),
325
+ [state, getState, setState, getKey, setKey, getIsInitial, addOptionsGetter]
326
+ );
229
327
 
230
- const onDispatchAction = useLatestCallback(
231
- (action: NavigationAction, noop: boolean) => {
232
- emitter.emit({
233
- type: '__unsafe_action__',
234
- data: { action, noop, stack: stackRef.current },
235
- });
236
- }
237
- );
328
+ const onReadyRef = React.useRef(onReady);
329
+ const onStateChangeRef = React.useRef(onStateChange);
238
330
 
239
- const onEmitEvent = useLatestCallback(
240
- (event: {
241
- type: string;
242
- defaultPrevented: boolean | undefined;
243
- target: string | undefined;
244
- data: unknown;
245
- }) => {
246
- emitter.emit({
247
- type: '__unsafe_event__',
248
- data: event,
249
- });
250
- }
251
- );
331
+ React.useEffect(() => {
332
+ isInitialRef.current = false;
333
+ onStateChangeRef.current = onStateChange;
334
+ onReadyRef.current = onReady;
335
+ });
252
336
 
253
- const lastEmittedOptionsRef = React.useRef<object | undefined>(undefined);
337
+ const onReadyCalledRef = React.useRef(false);
254
338
 
255
- const onOptionsChange = useLatestCallback((options: object) => {
256
- if (lastEmittedOptionsRef.current === options) {
257
- return;
258
- }
339
+ React.useEffect(() => {
340
+ if (!onReadyCalledRef.current && isReady()) {
341
+ onReadyCalledRef.current = true;
342
+ onReadyRef.current?.();
343
+ emitter.emit({ type: 'ready' });
344
+ }
345
+ }, [state, isReady, emitter]);
259
346
 
260
- lastEmittedOptionsRef.current = options;
347
+ React.useEffect(() => {
348
+ const hydratedState = getRootState();
261
349
 
262
- emitter.emit({
263
- type: 'options',
264
- data: { options },
265
- });
266
- });
350
+ if (process.env.NODE_ENV !== 'production') {
351
+ if (hydratedState !== undefined) {
352
+ const serializableResult = checkSerializable(hydratedState);
267
353
 
268
- const stackRef = React.useRef<string | undefined>(undefined);
269
-
270
- const builderContext = React.useMemo(
271
- () => ({
272
- addListener,
273
- addKeyedListener,
274
- onDispatchAction,
275
- onEmitEvent,
276
- onOptionsChange,
277
- scheduleUpdate,
278
- flushUpdates,
279
- stackRef,
280
- }),
281
- [
282
- addListener,
283
- addKeyedListener,
284
- onDispatchAction,
285
- onEmitEvent,
286
- onOptionsChange,
287
- scheduleUpdate,
288
- flushUpdates,
289
- ]
290
- );
354
+ if (!serializableResult.serializable) {
355
+ const { location, reason } = serializableResult;
291
356
 
292
- const isInitialRef = React.useRef(true);
293
-
294
- const getIsInitial = React.useCallback(() => isInitialRef.current, []);
295
-
296
- const context = React.useMemo(
297
- () => ({
298
- state,
299
- getState,
300
- setState,
301
- getKey,
302
- setKey,
303
- getIsInitial,
304
- addOptionsGetter,
305
- }),
306
- [
307
- state,
308
- getState,
309
- setState,
310
- getKey,
311
- setKey,
312
- getIsInitial,
313
- addOptionsGetter,
314
- ]
315
- );
357
+ let path = '';
358
+ let pointer: Record<any, any> = hydratedState;
359
+ let params = false;
316
360
 
317
- const onReadyRef = React.useRef(onReady);
318
- const onStateChangeRef = React.useRef(onStateChange);
361
+ for (let i = 0; i < location.length; i++) {
362
+ const curr = location[i];
363
+ const prev = location[i - 1];
319
364
 
320
- React.useEffect(() => {
321
- isInitialRef.current = false;
322
- onStateChangeRef.current = onStateChange;
323
- onReadyRef.current = onReady;
324
- });
365
+ if (curr == null) {
366
+ continue;
367
+ }
325
368
 
326
- const onReadyCalledRef = React.useRef(false);
369
+ pointer = pointer[curr];
327
370
 
328
- React.useEffect(() => {
329
- if (!onReadyCalledRef.current && isReady()) {
330
- onReadyCalledRef.current = true;
331
- onReadyRef.current?.();
332
- emitter.emit({ type: 'ready' });
333
- }
334
- }, [state, isReady, emitter]);
335
-
336
- React.useEffect(() => {
337
- const hydratedState = getRootState();
338
-
339
- if (process.env.NODE_ENV !== 'production') {
340
- if (hydratedState !== undefined) {
341
- const serializableResult = checkSerializable(hydratedState);
342
-
343
- if (!serializableResult.serializable) {
344
- const { location, reason } = serializableResult;
345
-
346
- let path = '';
347
- let pointer: Record<any, any> = hydratedState;
348
- let params = false;
349
-
350
- for (let i = 0; i < location.length; i++) {
351
- const curr = location[i];
352
- const prev = location[i - 1];
353
-
354
- pointer = pointer[curr];
355
-
356
- if (!params && curr === 'state') {
357
- continue;
358
- } else if (!params && curr === 'routes') {
359
- if (path) {
360
- path += ' > ';
361
- }
362
- } else if (
363
- !params &&
364
- typeof curr === 'number' &&
365
- prev === 'routes'
366
- ) {
367
- path += pointer?.name;
368
- } else if (!params) {
369
- path += ` > ${curr}`;
370
- params = true;
371
+ if (!params && curr === 'state') {
372
+ continue;
373
+ } else if (!params && curr === 'routes') {
374
+ if (path) {
375
+ path += ' > ';
376
+ }
377
+ } else if (
378
+ !params &&
379
+ typeof curr === 'number' &&
380
+ prev === 'routes'
381
+ ) {
382
+ path += pointer?.name;
383
+ } else if (!params) {
384
+ path += ` > ${curr}`;
385
+ params = true;
386
+ } else {
387
+ if (typeof curr === 'number' || /^[0-9]+$/.test(curr)) {
388
+ path += `[${curr}]`;
389
+ } else if (/^[a-z$_]+$/i.test(curr)) {
390
+ path += `.${curr}`;
371
391
  } else {
372
- if (typeof curr === 'number' || /^[0-9]+$/.test(curr)) {
373
- path += `[${curr}]`;
374
- } else if (/^[a-z$_]+$/i.test(curr)) {
375
- path += `.${curr}`;
376
- } else {
377
- path += `[${JSON.stringify(curr)}]`;
378
- }
392
+ path += `[${JSON.stringify(curr)}]`;
379
393
  }
380
394
  }
395
+ }
381
396
 
382
- const message = `Non-serializable values were found in the navigation state. Check:\n\n${path} (${reason})\n\nThis can break usage such as persisting and restoring state. This might happen if you passed non-serializable values such as function, class instances etc. in params. If you need to use components with callbacks in your options, you can use 'navigation.setOptions' instead. See https://reactnavigation.org/docs/troubleshooting#i-get-the-warning-non-serializable-values-were-found-in-the-navigation-state for more details.`;
397
+ const message = `Non-serializable values were found in the navigation state. Check:\n\n${path} (${reason})\n\nThis can break usage such as persisting and restoring state. This might happen if you passed non-serializable values such as function, class instances etc. in params. If you need to use components with callbacks in your options, you can use 'navigation.setOptions' instead. See https://reactnavigation.org/docs/troubleshooting#i-get-the-warning-non-serializable-values-were-found-in-the-navigation-state for more details.`;
383
398
 
384
- if (!serializableWarnings.includes(message)) {
385
- serializableWarnings.push(message);
386
- console.warn(message);
387
- }
399
+ if (!serializableWarnings.includes(message)) {
400
+ serializableWarnings.push(message);
401
+ console.warn(message);
388
402
  }
403
+ }
389
404
 
390
- const duplicateRouteNamesResult =
391
- checkDuplicateRouteNames(hydratedState);
405
+ const duplicateRouteNamesResult =
406
+ checkDuplicateRouteNames(hydratedState);
392
407
 
393
- if (duplicateRouteNamesResult.length) {
394
- const message = `Found screens with the same name nested inside one another. Check:\n${duplicateRouteNamesResult.map(
395
- (locations) => `\n${locations.join(', ')}`
396
- )}\n\nThis can cause confusing behavior during navigation. Consider using unique names for each screen instead.`;
408
+ if (duplicateRouteNamesResult.length) {
409
+ const message = `Found screens with the same name nested inside one another. Check:\n${duplicateRouteNamesResult.map(
410
+ (locations) => `\n${locations.join(', ')}`
411
+ )}\n\nThis can cause confusing behavior during navigation. Consider using unique names for each screen instead.`;
397
412
 
398
- if (!duplicateNameWarnings.includes(message)) {
399
- duplicateNameWarnings.push(message);
400
- console.warn(message);
401
- }
413
+ if (!duplicateNameWarnings.includes(message)) {
414
+ duplicateNameWarnings.push(message);
415
+ console.warn(message);
402
416
  }
403
417
  }
404
418
  }
419
+ }
405
420
 
406
- emitter.emit({ type: 'state', data: { state } });
407
-
408
- if (!isFirstMountRef.current && onStateChangeRef.current) {
409
- onStateChangeRef.current(hydratedState);
410
- }
421
+ lastEmittedStateRef.current = state;
411
422
 
412
- isFirstMountRef.current = false;
413
- }, [getRootState, emitter, state]);
423
+ emitter.emit({ type: 'state', data: { state } });
414
424
 
415
- const defaultOnUnhandledAction = useLatestCallback(
416
- (action: NavigationAction) => {
417
- if (process.env.NODE_ENV === 'production') {
418
- return;
419
- }
425
+ if (!isFirstMountRef.current && onStateChangeRef.current) {
426
+ onStateChangeRef.current(hydratedState);
427
+ }
420
428
 
421
- const payload: Record<string, any> | undefined = action.payload;
422
-
423
- let message = `The action '${action.type}'${
424
- payload ? ` with payload ${JSON.stringify(action.payload)}` : ''
425
- } was not handled by any navigator.`;
426
-
427
- switch (action.type) {
428
- case 'PRELOAD':
429
- case 'NAVIGATE':
430
- case 'PUSH':
431
- case 'REPLACE':
432
- case 'POP_TO':
433
- case 'JUMP_TO':
434
- if (payload?.name) {
435
- message += `\n\nDo you have a screen named '${payload.name}'?\n\nIf you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator.\n\nIf you're using conditional rendering, navigation will happen automatically and you shouldn't navigate manually, see.`;
436
- } else {
437
- message += `\n\nYou need to pass the name of the screen to navigate to.\n\nSee https://reactnavigation.org/docs/navigation-actions for usage.`;
438
- }
429
+ isFirstMountRef.current = false;
430
+ }, [getRootState, emitter, state]);
439
431
 
440
- break;
441
- case 'GO_BACK':
442
- case 'POP':
443
- case 'POP_TO_TOP':
444
- message += `\n\nIs there any screen to go back to?`;
445
- break;
446
- case 'OPEN_DRAWER':
447
- case 'CLOSE_DRAWER':
448
- case 'TOGGLE_DRAWER':
449
- message += `\n\nIs your screen inside a Drawer navigator?`;
450
- break;
451
- }
432
+ const defaultOnUnhandledAction = useLatestCallback(
433
+ (action: NavigationAction) => {
434
+ if (process.env.NODE_ENV === 'production') {
435
+ return;
436
+ }
452
437
 
453
- message += `\n\nThis is a development-only warning and won't be shown in production.`;
438
+ const payload: Record<string, any> | undefined = action.payload;
439
+
440
+ let message = `The action '${action.type}'${
441
+ payload ? ` with payload ${JSON.stringify(action.payload)}` : ''
442
+ } was not handled by any navigator.`;
443
+
444
+ switch (action.type) {
445
+ case 'PRELOAD':
446
+ case 'NAVIGATE':
447
+ case 'PUSH':
448
+ case 'REPLACE':
449
+ case 'POP_TO':
450
+ case 'JUMP_TO':
451
+ if (payload?.name) {
452
+ message += `\n\nDo you have a screen named '${payload.name}'?\n\nIf you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator.\n\nIf you're using conditional rendering, navigation will happen automatically and you shouldn't navigate manually, see.`;
453
+ } else {
454
+ message += `\n\nYou need to pass the name of the screen to navigate to.\n\nSee https://reactnavigation.org/docs/navigation-actions for usage.`;
455
+ }
454
456
 
455
- console.error(message);
457
+ break;
458
+ case 'GO_BACK':
459
+ case 'POP':
460
+ case 'POP_TO_TOP':
461
+ message += `\n\nIs there any screen to go back to?`;
462
+ break;
463
+ case 'OPEN_DRAWER':
464
+ case 'CLOSE_DRAWER':
465
+ case 'TOGGLE_DRAWER':
466
+ message += `\n\nIs your screen inside a Drawer navigator?`;
467
+ break;
456
468
  }
457
- );
458
469
 
459
- return (
460
- <NavigationIndependentTreeContext.Provider value={false}>
461
- <NavigationContainerRefContext.Provider value={navigation}>
462
- <NavigationBuilderContext.Provider value={builderContext}>
463
- <NavigationStateContext.Provider value={context}>
470
+ message += `\n\nThis is a development-only warning and won't be shown in production.`;
471
+
472
+ console.error(message);
473
+ }
474
+ );
475
+
476
+ return (
477
+ <NavigationIndependentTreeContext.Provider value={false}>
478
+ <NavigationContainerRefContext.Provider value={navigation}>
479
+ <NavigationBuilderContext.Provider value={builderContext}>
480
+ <NavigationStateContext.Provider value={context}>
481
+ <ConsumedParamsContext.Provider value={consumedParams}>
464
482
  <UnhandledActionContext.Provider
465
483
  value={onUnhandledAction ?? defaultOnUnhandledAction}
466
484
  >
@@ -468,10 +486,10 @@ export const BaseNavigationContainer = React.forwardRef(
468
486
  <ThemeProvider value={theme}>{children}</ThemeProvider>
469
487
  </EnsureSingleNavigator>
470
488
  </UnhandledActionContext.Provider>
471
- </NavigationStateContext.Provider>
472
- </NavigationBuilderContext.Provider>
473
- </NavigationContainerRefContext.Provider>
474
- </NavigationIndependentTreeContext.Provider>
475
- );
476
- }
477
- );
489
+ </ConsumedParamsContext.Provider>
490
+ </NavigationStateContext.Provider>
491
+ </NavigationBuilderContext.Provider>
492
+ </NavigationContainerRefContext.Provider>
493
+ </NavigationIndependentTreeContext.Provider>
494
+ );
495
+ }