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

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 (285) hide show
  1. package/lib/module/BaseNavigationContainer.js +38 -19
  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 +20 -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 +3 -0
  14. package/lib/module/NavigationStateContext.js.map +1 -1
  15. package/lib/module/PreventRemoveContext.js.map +1 -1
  16. package/lib/module/PreventRemoveProvider.js +37 -27
  17. package/lib/module/PreventRemoveProvider.js.map +1 -1
  18. package/lib/module/SceneView.js +10 -41
  19. package/lib/module/SceneView.js.map +1 -1
  20. package/lib/module/StaticNavigation.js +179 -50
  21. package/lib/module/StaticNavigation.js.map +1 -1
  22. package/lib/module/StaticTreeContext.js +5 -0
  23. package/lib/module/StaticTreeContext.js.map +1 -0
  24. package/lib/module/checkSerializable.js +18 -13
  25. package/lib/module/checkSerializable.js.map +1 -1
  26. package/lib/module/createNavigationContainerRef.js +6 -8
  27. package/lib/module/createNavigationContainerRef.js.map +1 -1
  28. package/lib/module/createNavigatorFactory.js +27 -5
  29. package/lib/module/createNavigatorFactory.js.map +1 -1
  30. package/lib/module/findFocusedRoute.js +7 -4
  31. package/lib/module/findFocusedRoute.js.map +1 -1
  32. package/lib/module/getActionFromState.js +45 -20
  33. package/lib/module/getActionFromState.js.map +1 -1
  34. package/lib/module/getPathFromState.js +171 -90
  35. package/lib/module/getPathFromState.js.map +1 -1
  36. package/lib/module/getPatternParts.js +20 -4
  37. package/lib/module/getPatternParts.js.map +1 -1
  38. package/lib/module/getStateFromPath.js +487 -217
  39. package/lib/module/getStateFromPath.js.map +1 -1
  40. package/lib/module/getStateFromRouteParams.js +23 -0
  41. package/lib/module/getStateFromRouteParams.js.map +1 -0
  42. package/lib/module/index.js +5 -4
  43. package/lib/module/index.js.map +1 -1
  44. package/lib/module/theming/useTheme.js +1 -1
  45. package/lib/module/theming/useTheme.js.map +1 -1
  46. package/lib/module/types.js +35 -0
  47. package/lib/module/types.js.map +1 -1
  48. package/lib/module/useDescriptors.js +21 -11
  49. package/lib/module/useDescriptors.js.map +1 -1
  50. package/lib/module/useEventEmitter.js +48 -33
  51. package/lib/module/useEventEmitter.js.map +1 -1
  52. package/lib/module/useFocusEvents.js +12 -4
  53. package/lib/module/useFocusEvents.js.map +1 -1
  54. package/lib/module/useFocusedListenersChildrenAdapter.js +2 -2
  55. package/lib/module/useFocusedListenersChildrenAdapter.js.map +1 -1
  56. package/lib/module/useIsFocused.js +7 -12
  57. package/lib/module/useIsFocused.js.map +1 -1
  58. package/lib/module/useKeyedChildListeners.js +4 -2
  59. package/lib/module/useKeyedChildListeners.js.map +1 -1
  60. package/lib/module/useLazyValue.js.map +1 -1
  61. package/lib/module/useNavigation.js +2 -15
  62. package/lib/module/useNavigation.js.map +1 -1
  63. package/lib/module/useNavigationBuilder.js +204 -131
  64. package/lib/module/useNavigationBuilder.js.map +1 -1
  65. package/lib/module/useNavigationCache.js +22 -17
  66. package/lib/module/useNavigationCache.js.map +1 -1
  67. package/lib/module/useNavigationHelpers.js +28 -10
  68. package/lib/module/useNavigationHelpers.js.map +1 -1
  69. package/lib/module/useNavigationIndependentTree.js +1 -1
  70. package/lib/module/useNavigationIndependentTree.js.map +1 -1
  71. package/lib/module/useNavigationState.js +125 -45
  72. package/lib/module/useNavigationState.js.map +1 -1
  73. package/lib/module/useOnAction.js +37 -7
  74. package/lib/module/useOnAction.js.map +1 -1
  75. package/lib/module/useOnGetState.js +6 -3
  76. package/lib/module/useOnGetState.js.map +1 -1
  77. package/lib/module/useOnPreventRemove.js +39 -30
  78. package/lib/module/useOnPreventRemove.js.map +1 -1
  79. package/lib/module/useOnRouteFocus.js +1 -1
  80. package/lib/module/useOnRouteFocus.js.map +1 -1
  81. package/lib/module/useOptionsGetters.js +10 -5
  82. package/lib/module/useOptionsGetters.js.map +1 -1
  83. package/lib/module/usePreventRemove.js +10 -3
  84. package/lib/module/usePreventRemove.js.map +1 -1
  85. package/lib/module/usePreventRemoveContext.js +1 -1
  86. package/lib/module/usePreventRemoveContext.js.map +1 -1
  87. package/lib/module/useRegisterNavigator.js +2 -2
  88. package/lib/module/useRegisterNavigator.js.map +1 -1
  89. package/lib/module/useRoute.js +2 -0
  90. package/lib/module/useRoute.js.map +1 -1
  91. package/lib/module/useRouteCache.js +17 -11
  92. package/lib/module/useRouteCache.js.map +1 -1
  93. package/lib/module/useScheduleUpdate.js +9 -9
  94. package/lib/module/useScheduleUpdate.js.map +1 -1
  95. package/lib/module/useStateForPath.js +1 -1
  96. package/lib/module/useStateForPath.js.map +1 -1
  97. package/lib/module/useSyncState.js +32 -9
  98. package/lib/module/useSyncState.js.map +1 -1
  99. package/lib/module/validatePathConfig.js +50 -36
  100. package/lib/module/validatePathConfig.js.map +1 -1
  101. package/lib/typescript/src/BaseNavigationContainer.d.ts +6 -3
  102. package/lib/typescript/src/BaseNavigationContainer.d.ts.map +1 -1
  103. package/lib/typescript/src/ConsumedParamsContext.d.ts +3 -0
  104. package/lib/typescript/src/ConsumedParamsContext.d.ts.map +1 -0
  105. package/lib/typescript/src/DataLoading.d.ts +21 -0
  106. package/lib/typescript/src/DataLoading.d.ts.map +1 -0
  107. package/lib/typescript/src/EnsureSingleNavigator.d.ts +1 -1
  108. package/lib/typescript/src/EnsureSingleNavigator.d.ts.map +1 -1
  109. package/lib/typescript/src/Group.d.ts +1 -1
  110. package/lib/typescript/src/Group.d.ts.map +1 -1
  111. package/lib/typescript/src/NavigationBuilderContext.d.ts +9 -8
  112. package/lib/typescript/src/NavigationBuilderContext.d.ts.map +1 -1
  113. package/lib/typescript/src/NavigationContainerRefContext.d.ts +1 -1
  114. package/lib/typescript/src/NavigationContainerRefContext.d.ts.map +1 -1
  115. package/lib/typescript/src/NavigationFocusedRouteStateContext.d.ts +4 -4
  116. package/lib/typescript/src/NavigationFocusedRouteStateContext.d.ts.map +1 -1
  117. package/lib/typescript/src/NavigationHelpersContext.d.ts +1 -1
  118. package/lib/typescript/src/NavigationHelpersContext.d.ts.map +1 -1
  119. package/lib/typescript/src/NavigationIndependentTree.d.ts +1 -1
  120. package/lib/typescript/src/NavigationIndependentTree.d.ts.map +1 -1
  121. package/lib/typescript/src/NavigationProvider.d.ts +12 -13
  122. package/lib/typescript/src/NavigationProvider.d.ts.map +1 -1
  123. package/lib/typescript/src/NavigationStateContext.d.ts +4 -3
  124. package/lib/typescript/src/NavigationStateContext.d.ts.map +1 -1
  125. package/lib/typescript/src/PreventRemoveContext.d.ts +1 -0
  126. package/lib/typescript/src/PreventRemoveContext.d.ts.map +1 -1
  127. package/lib/typescript/src/PreventRemoveProvider.d.ts +1 -1
  128. package/lib/typescript/src/PreventRemoveProvider.d.ts.map +1 -1
  129. package/lib/typescript/src/SceneView.d.ts +4 -2
  130. package/lib/typescript/src/SceneView.d.ts.map +1 -1
  131. package/lib/typescript/src/Screen.d.ts +1 -1
  132. package/lib/typescript/src/Screen.d.ts.map +1 -1
  133. package/lib/typescript/src/StaticContainer.d.ts +1 -1
  134. package/lib/typescript/src/StaticContainer.d.ts.map +1 -1
  135. package/lib/typescript/src/StaticNavigation.d.ts +189 -109
  136. package/lib/typescript/src/StaticNavigation.d.ts.map +1 -1
  137. package/lib/typescript/src/StaticTreeContext.d.ts +4 -0
  138. package/lib/typescript/src/StaticTreeContext.d.ts.map +1 -0
  139. package/lib/typescript/src/checkSerializable.d.ts +8 -4
  140. package/lib/typescript/src/checkSerializable.d.ts.map +1 -1
  141. package/lib/typescript/src/createNavigationContainerRef.d.ts +1 -1
  142. package/lib/typescript/src/createNavigationContainerRef.d.ts.map +1 -1
  143. package/lib/typescript/src/createNavigatorFactory.d.ts +23 -5
  144. package/lib/typescript/src/createNavigatorFactory.d.ts.map +1 -1
  145. package/lib/typescript/src/findFocusedRoute.d.ts +3 -8
  146. package/lib/typescript/src/findFocusedRoute.d.ts.map +1 -1
  147. package/lib/typescript/src/getActionFromState.d.ts +4 -4
  148. package/lib/typescript/src/getActionFromState.d.ts.map +1 -1
  149. package/lib/typescript/src/getPathFromState.d.ts +3 -3
  150. package/lib/typescript/src/getPathFromState.d.ts.map +1 -1
  151. package/lib/typescript/src/getPatternParts.d.ts +1 -0
  152. package/lib/typescript/src/getPatternParts.d.ts.map +1 -1
  153. package/lib/typescript/src/getStateFromPath.d.ts +4 -7
  154. package/lib/typescript/src/getStateFromPath.d.ts.map +1 -1
  155. package/lib/typescript/src/getStateFromRouteParams.d.ts +3 -0
  156. package/lib/typescript/src/getStateFromRouteParams.d.ts.map +1 -0
  157. package/lib/typescript/src/index.d.ts +36 -33
  158. package/lib/typescript/src/index.d.ts.map +1 -1
  159. package/lib/typescript/src/theming/ThemeContext.d.ts +1 -1
  160. package/lib/typescript/src/theming/ThemeContext.d.ts.map +1 -1
  161. package/lib/typescript/src/theming/ThemeProvider.d.ts +2 -2
  162. package/lib/typescript/src/theming/ThemeProvider.d.ts.map +1 -1
  163. package/lib/typescript/src/theming/useTheme.d.ts +1 -1
  164. package/lib/typescript/src/theming/useTheme.d.ts.map +1 -1
  165. package/lib/typescript/src/types.d.ts +260 -159
  166. package/lib/typescript/src/types.d.ts.map +1 -1
  167. package/lib/typescript/src/useChildListeners.d.ts +3 -3
  168. package/lib/typescript/src/useChildListeners.d.ts.map +1 -1
  169. package/lib/typescript/src/useComponent.d.ts +1 -1
  170. package/lib/typescript/src/useComponent.d.ts.map +1 -1
  171. package/lib/typescript/src/useDescriptors.d.ts +10 -9
  172. package/lib/typescript/src/useDescriptors.d.ts.map +1 -1
  173. package/lib/typescript/src/useEventEmitter.d.ts +2 -2
  174. package/lib/typescript/src/useEventEmitter.d.ts.map +1 -1
  175. package/lib/typescript/src/useFocusEvents.d.ts +2 -2
  176. package/lib/typescript/src/useFocusEvents.d.ts.map +1 -1
  177. package/lib/typescript/src/useFocusedListenersChildrenAdapter.d.ts +2 -2
  178. package/lib/typescript/src/useFocusedListenersChildrenAdapter.d.ts.map +1 -1
  179. package/lib/typescript/src/useIsFocused.d.ts +3 -0
  180. package/lib/typescript/src/useIsFocused.d.ts.map +1 -1
  181. package/lib/typescript/src/useKeyedChildListeners.d.ts +3 -3
  182. package/lib/typescript/src/useKeyedChildListeners.d.ts.map +1 -1
  183. package/lib/typescript/src/useLazyValue.d.ts.map +1 -1
  184. package/lib/typescript/src/useNavigation.d.ts +4 -2
  185. package/lib/typescript/src/useNavigation.d.ts.map +1 -1
  186. package/lib/typescript/src/useNavigationBuilder.d.ts +23 -30
  187. package/lib/typescript/src/useNavigationBuilder.d.ts.map +1 -1
  188. package/lib/typescript/src/useNavigationCache.d.ts +3 -3
  189. package/lib/typescript/src/useNavigationCache.d.ts.map +1 -1
  190. package/lib/typescript/src/useNavigationContainerRef.d.ts +1 -1
  191. package/lib/typescript/src/useNavigationContainerRef.d.ts.map +1 -1
  192. package/lib/typescript/src/useNavigationHelpers.d.ts +19 -27
  193. package/lib/typescript/src/useNavigationHelpers.d.ts.map +1 -1
  194. package/lib/typescript/src/useNavigationState.d.ts +17 -3
  195. package/lib/typescript/src/useNavigationState.d.ts.map +1 -1
  196. package/lib/typescript/src/useOnAction.d.ts +9 -9
  197. package/lib/typescript/src/useOnAction.d.ts.map +1 -1
  198. package/lib/typescript/src/useOnGetState.d.ts +1 -1
  199. package/lib/typescript/src/useOnGetState.d.ts.map +1 -1
  200. package/lib/typescript/src/useOnPreventRemove.d.ts +5 -9
  201. package/lib/typescript/src/useOnPreventRemove.d.ts.map +1 -1
  202. package/lib/typescript/src/useOnRouteFocus.d.ts +6 -6
  203. package/lib/typescript/src/useOnRouteFocus.d.ts.map +1 -1
  204. package/lib/typescript/src/useOptionsGetters.d.ts +1 -1
  205. package/lib/typescript/src/useOptionsGetters.d.ts.map +1 -1
  206. package/lib/typescript/src/usePreventRemove.d.ts.map +1 -1
  207. package/lib/typescript/src/usePreventRemoveContext.d.ts +2 -1
  208. package/lib/typescript/src/usePreventRemoveContext.d.ts.map +1 -1
  209. package/lib/typescript/src/useRoute.d.ts +7 -3
  210. package/lib/typescript/src/useRoute.d.ts.map +1 -1
  211. package/lib/typescript/src/useRouteCache.d.ts +5 -5
  212. package/lib/typescript/src/useRouteCache.d.ts.map +1 -1
  213. package/lib/typescript/src/useScheduleUpdate.d.ts +5 -4
  214. package/lib/typescript/src/useScheduleUpdate.d.ts.map +1 -1
  215. package/lib/typescript/src/useStateForPath.d.ts +1 -1
  216. package/lib/typescript/src/useStateForPath.d.ts.map +1 -1
  217. package/lib/typescript/src/useSyncState.d.ts +1 -0
  218. package/lib/typescript/src/useSyncState.d.ts.map +1 -1
  219. package/lib/typescript/src/utilities.d.ts +74 -37
  220. package/lib/typescript/src/utilities.d.ts.map +1 -1
  221. package/lib/typescript/src/validatePathConfig.d.ts.map +1 -1
  222. package/package.json +23 -22
  223. package/src/BaseNavigationContainer.tsx +362 -334
  224. package/src/ConsumedParamsContext.tsx +5 -0
  225. package/src/DataLoading.tsx +203 -0
  226. package/src/NavigationBuilderContext.tsx +14 -9
  227. package/src/NavigationFocusedRouteStateContext.tsx +4 -4
  228. package/src/NavigationIndependentTree.tsx +23 -12
  229. package/src/NavigationProvider.tsx +26 -15
  230. package/src/NavigationStateContext.tsx +9 -6
  231. package/src/PreventRemoveContext.tsx +1 -0
  232. package/src/PreventRemoveProvider.tsx +51 -46
  233. package/src/SceneView.tsx +11 -39
  234. package/src/StaticNavigation.tsx +659 -307
  235. package/src/StaticTreeContext.tsx +7 -0
  236. package/src/checkSerializable.tsx +35 -19
  237. package/src/createNavigationContainerRef.tsx +12 -9
  238. package/src/createNavigatorFactory.tsx +92 -8
  239. package/src/findFocusedRoute.tsx +16 -16
  240. package/src/getActionFromState.tsx +87 -51
  241. package/src/getPathFromState.tsx +254 -128
  242. package/src/getPatternParts.tsx +25 -4
  243. package/src/getStateFromPath.tsx +821 -331
  244. package/src/getStateFromRouteParams.tsx +59 -0
  245. package/src/index.tsx +55 -5
  246. package/src/theming/useTheme.tsx +1 -1
  247. package/src/types.tsx +798 -373
  248. package/src/useDescriptors.tsx +31 -14
  249. package/src/useEventEmitter.tsx +52 -38
  250. package/src/useFocusEvents.tsx +15 -7
  251. package/src/useFocusedListenersChildrenAdapter.tsx +2 -2
  252. package/src/useIsFocused.tsx +14 -21
  253. package/src/useKeyedChildListeners.tsx +4 -2
  254. package/src/useLazyValue.tsx +2 -2
  255. package/src/useNavigation.tsx +7 -24
  256. package/src/useNavigationBuilder.tsx +314 -186
  257. package/src/useNavigationCache.tsx +32 -25
  258. package/src/useNavigationHelpers.tsx +27 -10
  259. package/src/useNavigationIndependentTree.tsx +1 -1
  260. package/src/useNavigationState.tsx +168 -69
  261. package/src/useOnAction.tsx +61 -13
  262. package/src/useOnGetState.tsx +5 -3
  263. package/src/useOnPreventRemove.tsx +75 -42
  264. package/src/useOnRouteFocus.tsx +10 -12
  265. package/src/useOptionsGetters.tsx +11 -5
  266. package/src/usePreventRemove.tsx +12 -3
  267. package/src/usePreventRemoveContext.tsx +1 -1
  268. package/src/useRegisterNavigator.tsx +2 -2
  269. package/src/useRoute.tsx +20 -6
  270. package/src/useRouteCache.tsx +22 -16
  271. package/src/useScheduleUpdate.tsx +9 -10
  272. package/src/useStateForPath.tsx +1 -1
  273. package/src/useSyncState.tsx +35 -9
  274. package/src/utilities.tsx +144 -31
  275. package/src/validatePathConfig.tsx +86 -57
  276. package/lib/module/CurrentRenderContext.js +0 -10
  277. package/lib/module/CurrentRenderContext.js.map +0 -1
  278. package/lib/module/useCurrentRender.js +0 -19
  279. package/lib/module/useCurrentRender.js.map +0 -1
  280. package/lib/typescript/src/CurrentRenderContext.d.ts +0 -9
  281. package/lib/typescript/src/CurrentRenderContext.d.ts.map +0 -1
  282. package/lib/typescript/src/useCurrentRender.d.ts +0 -14
  283. package/lib/typescript/src/useCurrentRender.d.ts.map +0 -1
  284. package/src/CurrentRenderContext.tsx +0 -9
  285. package/src/useCurrentRender.tsx +0 -31
@@ -78,6 +78,7 @@ type Options<
78
78
  onAction: (action: NavigationAction) => boolean;
79
79
  getState: () => State;
80
80
  setState: (state: State) => void;
81
+ subscribe: (callback: () => void) => () => void;
81
82
  addListener: AddListener;
82
83
  addKeyedListener: AddKeyedListener;
83
84
  onRouteFocus: (key: string) => void;
@@ -107,16 +108,17 @@ export function useDescriptors<
107
108
  onAction,
108
109
  getState,
109
110
  setState,
111
+ subscribe,
110
112
  addListener,
111
113
  addKeyedListener,
112
114
  onRouteFocus,
113
115
  router,
114
116
  emitter,
115
117
  }: Options<State, ScreenOptions, EventMap>) {
116
- const theme = React.useContext(ThemeContext);
117
- const [options, setOptions] = React.useState<Record<string, ScreenOptions>>(
118
- {}
119
- );
118
+ const theme = React.use(ThemeContext);
119
+ const [options, setOptions] = React.useState<
120
+ Record<string, Partial<ScreenOptions> | undefined>
121
+ >({});
120
122
  const {
121
123
  onDispatchAction,
122
124
  onEmitEvent,
@@ -124,7 +126,8 @@ export function useDescriptors<
124
126
  scheduleUpdate,
125
127
  flushUpdates,
126
128
  stackRef,
127
- } = React.useContext(NavigationBuilderContext);
129
+ getIsStateEmitted,
130
+ } = React.use(NavigationBuilderContext);
128
131
 
129
132
  const context = React.useMemo(
130
133
  () => ({
@@ -136,6 +139,7 @@ export function useDescriptors<
136
139
  onDispatchAction,
137
140
  onEmitEvent,
138
141
  onOptionsChange,
142
+ getIsStateEmitted,
139
143
  scheduleUpdate,
140
144
  flushUpdates,
141
145
  stackRef,
@@ -149,6 +153,7 @@ export function useDescriptors<
149
153
  onDispatchAction,
150
154
  onEmitEvent,
151
155
  onOptionsChange,
156
+ getIsStateEmitted,
152
157
  scheduleUpdate,
153
158
  flushUpdates,
154
159
  stackRef,
@@ -180,20 +185,20 @@ export function useDescriptors<
180
185
  ScreenOptions,
181
186
  EventMap
182
187
  >,
183
- overrides: Record<string, ScreenOptions>
188
+ overrides: Partial<ScreenOptions> | undefined
184
189
  ) => {
185
190
  const config = screens[route.name];
186
- const screen = config.props;
191
+ const screen = config?.props;
187
192
 
188
193
  const optionsList = [
189
194
  // The default `screenOptions` passed to the navigator
190
195
  screenOptions,
191
196
  // The `screenOptions` props passed to `Group` elements
192
- ...((config.options
197
+ ...((config?.options
193
198
  ? config.options.filter(Boolean)
194
199
  : []) as ScreenOptionsOrCallback<ScreenOptions>[]),
195
200
  // The `options` prop passed to `Screen` elements,
196
- screen.options,
201
+ screen?.options,
197
202
  // The options set via `navigation.setOptions`
198
203
  overrides,
199
204
  ];
@@ -222,12 +227,15 @@ export function useDescriptors<
222
227
  routeState: NavigationState | PartialState<NavigationState> | undefined
223
228
  ) => {
224
229
  const config = screens[route.name];
225
- const screen = config.props;
230
+ const screen = config?.props;
231
+
232
+ if (screen == null) {
233
+ throw new Error(`Couldn't find a screen named '${route.name}'.`);
234
+ }
226
235
 
227
236
  const clearOptions = () =>
228
237
  setOptions((o) => {
229
238
  if (route.key in o) {
230
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
231
239
  const { [route.key]: _, ...rest } = o;
232
240
  return rest;
233
241
  }
@@ -239,7 +247,7 @@ export function useDescriptors<
239
247
  // The `layout` prop passed to `Screen` elements,
240
248
  screen.layout ??
241
249
  // The `screenLayout` props passed to `Group` elements
242
- config.layout ??
250
+ config?.layout ??
243
251
  // The default `screenLayout` passed to the navigator
244
252
  screenLayout;
245
253
 
@@ -251,6 +259,7 @@ export function useDescriptors<
251
259
  routeState={routeState}
252
260
  getState={getState}
253
261
  setState={setState}
262
+ subscribe={subscribe}
254
263
  options={customOptions}
255
264
  clearOptions={clearOptions}
256
265
  />
@@ -294,7 +303,15 @@ export function useDescriptors<
294
303
  >
295
304
  >((acc, route, i) => {
296
305
  const navigation = navigations[route.key];
297
- const customOptions = getOptions(route, navigation, options[route.key]);
306
+ const overrides = options[route.key];
307
+
308
+ if (navigation == null) {
309
+ throw new Error(
310
+ `Couldn't find a navigation object for route '${route.key}'.`
311
+ );
312
+ }
313
+
314
+ const customOptions = getOptions(route, navigation, overrides);
298
315
  const element = render(route, navigation, customOptions, routes[i]?.state);
299
316
 
300
317
  acc[route.key] = {
@@ -303,7 +320,7 @@ export function useDescriptors<
303
320
  render() {
304
321
  return element;
305
322
  },
306
- options: customOptions as ScreenOptions,
323
+ options: customOptions,
307
324
  };
308
325
 
309
326
  return acc;
@@ -13,12 +13,15 @@ type Listeners = Set<(e: any) => void>;
13
13
  * Hook to manage the event system used by the navigator to notify screens of various events.
14
14
  */
15
15
  export function useEventEmitter<T extends Record<string, any>>(
16
- listen?: (e: any) => void
16
+ listen?: (e: any) => void,
17
+ onPostEmit?: (e: any) => void
17
18
  ): NavigationEventEmitter<T> {
18
19
  const listenRef = React.useRef(listen);
20
+ const onPostEmitRef = React.useRef(onPostEmit);
19
21
 
20
- React.useEffect(() => {
22
+ React.useInsertionEffect(() => {
21
23
  listenRef.current = listen;
24
+ onPostEmitRef.current = onPostEmit;
22
25
  });
23
26
 
24
27
  const listeners = React.useRef<Record<string, Record<string, Listeners>>>(
@@ -59,62 +62,73 @@ export function useEventEmitter<T extends Record<string, any>>(
59
62
  target?: string;
60
63
  canPreventDefault?: boolean;
61
64
  }) => {
62
- const items = listeners.current[type] || {};
65
+ const items = listeners.current[type];
63
66
 
64
67
  // Copy the current list of callbacks in case they are mutated during execution
65
- const callbacks = new Set(
66
- Object.values(target ? { [target]: items[target] } : items).flatMap(
67
- (t) => (t ? Array.from(t) : [])
68
- )
69
- );
68
+ let callbacks: Set<(e: any) => void> | undefined;
69
+
70
+ if (items) {
71
+ if (target !== undefined) {
72
+ const targetSet = items[target];
73
+
74
+ if (targetSet && targetSet.size) {
75
+ callbacks = new Set(targetSet);
76
+ }
77
+ } else {
78
+ for (const key in items) {
79
+ const set = items[key];
80
+
81
+ if (set && set.size) {
82
+ callbacks ??= new Set();
83
+
84
+ for (const cb of set) {
85
+ callbacks.add(cb);
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
70
91
 
71
- const event: EventArg<any, any, any> = {
72
- get type() {
73
- return type;
74
- },
92
+ const descriptors: PropertyDescriptorMap = {
93
+ type: { enumerable: true, value: type },
75
94
  };
76
95
 
77
96
  if (target !== undefined) {
78
- Object.defineProperty(event, 'target', {
79
- enumerable: true,
80
- get() {
81
- return target;
82
- },
83
- });
97
+ descriptors.target = { enumerable: true, value: target };
84
98
  }
85
99
 
86
100
  if (data !== undefined) {
87
- Object.defineProperty(event, 'data', {
88
- enumerable: true,
89
- get() {
90
- return data;
91
- },
92
- });
101
+ descriptors.data = { enumerable: true, value: data };
93
102
  }
94
103
 
104
+ let defaultPrevented = false;
105
+
95
106
  if (canPreventDefault) {
96
- let defaultPrevented = false;
97
-
98
- Object.defineProperties(event, {
99
- defaultPrevented: {
100
- enumerable: true,
101
- get() {
102
- return defaultPrevented;
103
- },
107
+ descriptors.defaultPrevented = {
108
+ enumerable: true,
109
+ get() {
110
+ return defaultPrevented;
104
111
  },
105
- preventDefault: {
106
- enumerable: true,
107
- value() {
108
- defaultPrevented = true;
109
- },
112
+ };
113
+ descriptors.preventDefault = {
114
+ enumerable: true,
115
+ value() {
116
+ defaultPrevented = true;
110
117
  },
111
- });
118
+ };
112
119
  }
113
120
 
121
+ const event: EventArg<any, any, any> = Object.defineProperties(
122
+ {} as EventArg<any, any, any>,
123
+ descriptors
124
+ );
125
+
114
126
  listenRef.current?.(event);
115
127
 
116
128
  callbacks?.forEach((cb) => cb(event));
117
129
 
130
+ onPostEmitRef.current?.(event);
131
+
118
132
  return event as any;
119
133
  },
120
134
  []
@@ -17,10 +17,16 @@ export function useFocusEvents<State extends NavigationState>({
17
17
  state,
18
18
  emitter,
19
19
  }: Options<State>) {
20
- const navigation = React.useContext(NavigationContext);
20
+ const navigation = React.use(NavigationContext);
21
21
  const lastFocusedKeyRef = React.useRef<string | undefined>(undefined);
22
22
 
23
- const currentFocusedKey = state.routes[state.index].key;
23
+ const currentFocusedRoute = state.routes[state.index];
24
+
25
+ if (currentFocusedRoute == null) {
26
+ throw new Error(`Couldn't find a route at index ${state.index}.`);
27
+ }
28
+
29
+ const currentFocusedKey = currentFocusedRoute.key;
24
30
 
25
31
  // When the parent screen changes its focus state, we also need to change child's focus
26
32
  // Coz the child screen can't be focused if the parent screen is out of focus
@@ -45,7 +51,12 @@ export function useFocusEvents<State extends NavigationState>({
45
51
  React.useEffect(() => {
46
52
  const lastFocusedKey = lastFocusedKeyRef.current;
47
53
 
48
- lastFocusedKeyRef.current = currentFocusedKey;
54
+ const isFocused = navigation ? navigation.isFocused() : true;
55
+
56
+ if (isFocused) {
57
+ // Remember the current route as focused if the navigator is focused
58
+ lastFocusedKeyRef.current = currentFocusedKey;
59
+ }
49
60
 
50
61
  // We wouldn't have `lastFocusedKey` on initial mount
51
62
  // Fire focus event for the current route on mount if there's no parent navigator
@@ -55,10 +66,7 @@ export function useFocusEvents<State extends NavigationState>({
55
66
 
56
67
  // We should only emit events when the focused key changed and navigator is focused
57
68
  // When navigator is not focused, screens inside shouldn't receive focused status either
58
- if (
59
- lastFocusedKey === currentFocusedKey ||
60
- !(navigation ? navigation.isFocused() : true)
61
- ) {
69
+ if (lastFocusedKey === currentFocusedKey || !isFocused) {
62
70
  return;
63
71
  }
64
72
 
@@ -20,7 +20,7 @@ export function useFocusedListenersChildrenAdapter({
20
20
  navigation,
21
21
  focusedListeners,
22
22
  }: Options) {
23
- const { addListener } = React.useContext(NavigationBuilderContext);
23
+ const { addListener } = React.use(NavigationBuilderContext);
24
24
 
25
25
  const listener = React.useCallback(
26
26
  (callback: FocusedNavigationCallback<any>) => {
@@ -41,7 +41,7 @@ export function useFocusedListenersChildrenAdapter({
41
41
  [focusedListeners, navigation]
42
42
  );
43
43
 
44
- React.useEffect(
44
+ React.useInsertionEffect(
45
45
  () => addListener?.('focus', listener),
46
46
  [addListener, listener]
47
47
  );
@@ -1,32 +1,25 @@
1
1
  import * as React from 'react';
2
2
 
3
- import { useNavigation } from './useNavigation';
3
+ export const FocusedRouteKeyContext = React.createContext<string | undefined>(
4
+ undefined
5
+ );
6
+
7
+ export const IsFocusedContext = React.createContext<boolean | undefined>(
8
+ undefined
9
+ );
4
10
 
5
11
  /**
6
12
  * Hook to get the current focus state of the screen. Returns a `true` if screen is focused, otherwise `false`.
7
13
  * This can be used if a component needs to render something based on the focus state.
8
14
  */
9
15
  export function useIsFocused(): boolean {
10
- const navigation = useNavigation();
11
-
12
- const subscribe = React.useCallback(
13
- (callback: () => void) => {
14
- const unsubscribeFocus = navigation.addListener('focus', callback);
15
- const unsubscribeBlur = navigation.addListener('blur', callback);
16
-
17
- return () => {
18
- unsubscribeFocus();
19
- unsubscribeBlur();
20
- };
21
- },
22
- [navigation]
23
- );
16
+ const isFocused = React.use(IsFocusedContext);
24
17
 
25
- const value = React.useSyncExternalStore(
26
- subscribe,
27
- navigation.isFocused,
28
- navigation.isFocused
29
- );
18
+ if (isFocused === undefined) {
19
+ throw new Error(
20
+ "Couldn't determine focus state. Is your component inside a screen in a navigator?"
21
+ );
22
+ }
30
23
 
31
- return value;
24
+ return isFocused;
32
25
  }
@@ -28,8 +28,10 @@ export function useKeyedChildListeners() {
28
28
  keyedListeners[type][key] = listener;
29
29
 
30
30
  return () => {
31
- // @ts-expect-error: according to ref stated above you can use `key` to index type
32
- keyedListeners[type][key] = undefined;
31
+ if (keyedListeners[type][key] === listener) {
32
+ // @ts-expect-error: according to ref stated above you can use `key` to index type
33
+ keyedListeners[type][key] = undefined;
34
+ }
33
35
  };
34
36
  },
35
37
  [keyedListeners]
@@ -1,11 +1,11 @@
1
1
  import * as React from 'react';
2
2
 
3
- export function useLazyValue<T>(create: () => T) {
3
+ export function useLazyValue<T>(create: () => T): T {
4
4
  const lazyRef = React.useRef<T>(undefined);
5
5
 
6
6
  if (lazyRef.current === undefined) {
7
7
  lazyRef.current = create();
8
8
  }
9
9
 
10
- return lazyRef.current as T;
10
+ return lazyRef.current;
11
11
  }
@@ -1,10 +1,7 @@
1
1
  import * as React from 'react';
2
2
 
3
3
  import { NavigationContainerRefContext } from './NavigationContainerRefContext';
4
- import {
5
- NavigationContext,
6
- NavigationRouteNameContext,
7
- } from './NavigationProvider';
4
+ import { NavigationContext } from './NavigationProvider';
8
5
  import type {
9
6
  GenericNavigation,
10
7
  NavigationListForNavigator,
@@ -13,6 +10,8 @@ import type {
13
10
  RootParamList,
14
11
  } from './types';
15
12
 
13
+ type RootNavigation = GenericNavigation<RootParamList>;
14
+
16
15
  /**
17
16
  * Hook to access the navigation prop of the parent screen anywhere.
18
17
  *
@@ -21,14 +20,14 @@ import type {
21
20
  *
22
21
  * @returns Navigation prop of the parent screen.
23
22
  */
24
- export function useNavigation(): GenericNavigation<RootParamList>;
23
+ export function useNavigation(): RootNavigation;
25
24
  export function useNavigation<
26
25
  const Navigator = RootNavigator,
27
26
  >(): NavigationListForNavigator<Navigator>[keyof NavigationListForNavigator<Navigator>];
28
27
  export function useNavigation<
29
28
  const Navigator = RootNavigator,
30
- const RouteName extends
31
- keyof NavigationListForNested<Navigator> = keyof NavigationListForNested<Navigator>,
29
+ const RouteName extends keyof NavigationListForNested<Navigator> =
30
+ keyof NavigationListForNested<Navigator>,
32
31
  >(name: RouteName): NavigationListForNested<Navigator>[RouteName];
33
32
  export function useNavigation(name?: string): unknown {
34
33
  const root = React.use(NavigationContainerRefContext);
@@ -44,23 +43,7 @@ export function useNavigation(name?: string): unknown {
44
43
  return navigation ?? root;
45
44
  }
46
45
 
47
- const routeName = React.use(NavigationRouteNameContext);
48
-
49
- // Generally, this condition isn't needed as `getParent(name)` works for current screen
50
- // However, it'll throw if the hook is used in a preloaded screen
51
- if (routeName === name) {
52
- if (navigation === undefined) {
53
- throw new Error(
54
- `Couldn't find a navigation object for '${name}'. This is not expected.`
55
- );
56
- }
57
-
58
- return navigation;
59
- }
60
-
61
- // We get parent first so that `getParent(name)` is not called in preloaded screens
62
- // It's ok since `getParent` also works for current screen, so parent is not skipped
63
- const parent = navigation?.getParent()?.getParent(name);
46
+ const parent = navigation?.getParent(name);
64
47
 
65
48
  if (parent === undefined) {
66
49
  throw new Error(