@react-navigation/core 7.0.0-rc.0 → 7.0.0-rc.10

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 (156) hide show
  1. package/lib/commonjs/BaseNavigationContainer.js +43 -33
  2. package/lib/commonjs/BaseNavigationContainer.js.map +1 -1
  3. package/lib/commonjs/EnsureSingleNavigator.js +5 -3
  4. package/lib/commonjs/EnsureSingleNavigator.js.map +1 -1
  5. package/lib/commonjs/NavigationIndependentTree.js +14 -10
  6. package/lib/commonjs/NavigationIndependentTree.js.map +1 -1
  7. package/lib/commonjs/PreventRemoveProvider.js +8 -6
  8. package/lib/commonjs/PreventRemoveProvider.js.map +1 -1
  9. package/lib/commonjs/SceneView.js +23 -18
  10. package/lib/commonjs/SceneView.js.map +1 -1
  11. package/lib/commonjs/StaticNavigation.js +56 -35
  12. package/lib/commonjs/StaticNavigation.js.map +1 -1
  13. package/lib/commonjs/createNavigatorFactory.js +2 -2
  14. package/lib/commonjs/getFocusedRouteNameFromRoute.js +1 -1
  15. package/lib/commonjs/getPathFromState.js +1 -1
  16. package/lib/commonjs/getStateFromPath.js +2 -2
  17. package/lib/commonjs/index.js +32 -32
  18. package/lib/commonjs/package.json +1 -0
  19. package/lib/commonjs/theming/ThemeProvider.js +6 -4
  20. package/lib/commonjs/theming/ThemeProvider.js.map +1 -1
  21. package/lib/commonjs/theming/useTheme.js +1 -1
  22. package/lib/commonjs/types.js.map +1 -1
  23. package/lib/commonjs/useComponent.js +5 -3
  24. package/lib/commonjs/useComponent.js.map +1 -1
  25. package/lib/commonjs/useCurrentRender.js +1 -1
  26. package/lib/commonjs/useDescriptors.js +19 -16
  27. package/lib/commonjs/useDescriptors.js.map +1 -1
  28. package/lib/commonjs/useFocusEffect.js +1 -1
  29. package/lib/commonjs/useFocusEvents.js +1 -1
  30. package/lib/commonjs/useFocusedListenersChildrenAdapter.js +1 -1
  31. package/lib/commonjs/useIsFocused.js +7 -18
  32. package/lib/commonjs/useIsFocused.js.map +1 -1
  33. package/lib/commonjs/useNavigation.js +2 -2
  34. package/lib/commonjs/useNavigationBuilder.js +32 -28
  35. package/lib/commonjs/useNavigationBuilder.js.map +1 -1
  36. package/lib/commonjs/useNavigationCache.js +1 -1
  37. package/lib/commonjs/useNavigationContainerRef.js +1 -1
  38. package/lib/commonjs/useNavigationHelpers.js +3 -3
  39. package/lib/commonjs/useNavigationIndependentTree.js +1 -1
  40. package/lib/commonjs/useNavigationState.js +6 -16
  41. package/lib/commonjs/useNavigationState.js.map +1 -1
  42. package/lib/commonjs/useOnAction.js +3 -3
  43. package/lib/commonjs/useOnGetState.js +3 -3
  44. package/lib/commonjs/useOnPreventRemove.js +2 -2
  45. package/lib/commonjs/useOnRouteFocus.js +1 -1
  46. package/lib/commonjs/useOptionsGetters.js +2 -2
  47. package/lib/commonjs/usePreventRemove.js +3 -3
  48. package/lib/commonjs/usePreventRemoveContext.js +1 -1
  49. package/lib/commonjs/useRegisterNavigator.js +1 -1
  50. package/lib/commonjs/useRoute.js +1 -1
  51. package/lib/commonjs/useRouteCache.js +1 -1
  52. package/lib/commonjs/useSyncState.js +1 -1
  53. package/lib/module/BaseNavigationContainer.js +43 -33
  54. package/lib/module/BaseNavigationContainer.js.map +1 -1
  55. package/lib/module/EnsureSingleNavigator.js +5 -3
  56. package/lib/module/EnsureSingleNavigator.js.map +1 -1
  57. package/lib/module/NavigationIndependentTree.js +14 -10
  58. package/lib/module/NavigationIndependentTree.js.map +1 -1
  59. package/lib/module/PreventRemoveProvider.js +8 -6
  60. package/lib/module/PreventRemoveProvider.js.map +1 -1
  61. package/lib/module/SceneView.js +23 -18
  62. package/lib/module/SceneView.js.map +1 -1
  63. package/lib/module/StaticNavigation.js +55 -35
  64. package/lib/module/StaticNavigation.js.map +1 -1
  65. package/lib/module/createNavigatorFactory.js +2 -2
  66. package/lib/module/createNavigatorFactory.js.map +1 -1
  67. package/lib/module/getFocusedRouteNameFromRoute.js +1 -1
  68. package/lib/module/getFocusedRouteNameFromRoute.js.map +1 -1
  69. package/lib/module/getPathFromState.js +1 -1
  70. package/lib/module/getPathFromState.js.map +1 -1
  71. package/lib/module/getStateFromPath.js +2 -2
  72. package/lib/module/getStateFromPath.js.map +1 -1
  73. package/lib/module/index.js +32 -32
  74. package/lib/module/index.js.map +1 -1
  75. package/lib/module/package.json +1 -0
  76. package/lib/module/theming/ThemeProvider.js +6 -4
  77. package/lib/module/theming/ThemeProvider.js.map +1 -1
  78. package/lib/module/theming/useTheme.js +1 -1
  79. package/lib/module/theming/useTheme.js.map +1 -1
  80. package/lib/module/types.js.map +1 -1
  81. package/lib/module/useComponent.js +5 -3
  82. package/lib/module/useComponent.js.map +1 -1
  83. package/lib/module/useCurrentRender.js +1 -1
  84. package/lib/module/useCurrentRender.js.map +1 -1
  85. package/lib/module/useDescriptors.js +19 -16
  86. package/lib/module/useDescriptors.js.map +1 -1
  87. package/lib/module/useFocusEffect.js +1 -1
  88. package/lib/module/useFocusEffect.js.map +1 -1
  89. package/lib/module/useFocusEvents.js +1 -1
  90. package/lib/module/useFocusEvents.js.map +1 -1
  91. package/lib/module/useFocusedListenersChildrenAdapter.js +1 -1
  92. package/lib/module/useFocusedListenersChildrenAdapter.js.map +1 -1
  93. package/lib/module/useIsFocused.js +6 -17
  94. package/lib/module/useIsFocused.js.map +1 -1
  95. package/lib/module/useNavigation.js +2 -2
  96. package/lib/module/useNavigation.js.map +1 -1
  97. package/lib/module/useNavigationBuilder.js +32 -28
  98. package/lib/module/useNavigationBuilder.js.map +1 -1
  99. package/lib/module/useNavigationCache.js +1 -1
  100. package/lib/module/useNavigationCache.js.map +1 -1
  101. package/lib/module/useNavigationContainerRef.js +1 -1
  102. package/lib/module/useNavigationContainerRef.js.map +1 -1
  103. package/lib/module/useNavigationHelpers.js +3 -3
  104. package/lib/module/useNavigationHelpers.js.map +1 -1
  105. package/lib/module/useNavigationIndependentTree.js +1 -1
  106. package/lib/module/useNavigationIndependentTree.js.map +1 -1
  107. package/lib/module/useNavigationState.js +6 -16
  108. package/lib/module/useNavigationState.js.map +1 -1
  109. package/lib/module/useOnAction.js +3 -3
  110. package/lib/module/useOnAction.js.map +1 -1
  111. package/lib/module/useOnGetState.js +3 -3
  112. package/lib/module/useOnGetState.js.map +1 -1
  113. package/lib/module/useOnPreventRemove.js +2 -2
  114. package/lib/module/useOnPreventRemove.js.map +1 -1
  115. package/lib/module/useOnRouteFocus.js +1 -1
  116. package/lib/module/useOnRouteFocus.js.map +1 -1
  117. package/lib/module/useOptionsGetters.js +2 -2
  118. package/lib/module/useOptionsGetters.js.map +1 -1
  119. package/lib/module/usePreventRemove.js +3 -3
  120. package/lib/module/usePreventRemove.js.map +1 -1
  121. package/lib/module/usePreventRemoveContext.js +1 -1
  122. package/lib/module/usePreventRemoveContext.js.map +1 -1
  123. package/lib/module/useRegisterNavigator.js +1 -1
  124. package/lib/module/useRegisterNavigator.js.map +1 -1
  125. package/lib/module/useRoute.js +1 -1
  126. package/lib/module/useRoute.js.map +1 -1
  127. package/lib/module/useRouteCache.js +1 -1
  128. package/lib/module/useRouteCache.js.map +1 -1
  129. package/lib/module/useSyncState.js +1 -1
  130. package/lib/module/useSyncState.js.map +1 -1
  131. package/lib/typescript/src/EnsureSingleNavigator.d.ts +1 -1
  132. package/lib/typescript/src/EnsureSingleNavigator.d.ts.map +1 -1
  133. package/lib/typescript/src/NavigationIndependentTree.d.ts +1 -1
  134. package/lib/typescript/src/NavigationIndependentTree.d.ts.map +1 -1
  135. package/lib/typescript/src/PreventRemoveProvider.d.ts +1 -1
  136. package/lib/typescript/src/PreventRemoveProvider.d.ts.map +1 -1
  137. package/lib/typescript/src/SceneView.d.ts +1 -2
  138. package/lib/typescript/src/SceneView.d.ts.map +1 -1
  139. package/lib/typescript/src/StaticNavigation.d.ts +2 -4
  140. package/lib/typescript/src/StaticNavigation.d.ts.map +1 -1
  141. package/lib/typescript/src/theming/ThemeProvider.d.ts +1 -1
  142. package/lib/typescript/src/theming/ThemeProvider.d.ts.map +1 -1
  143. package/lib/typescript/src/types.d.ts +12 -7
  144. package/lib/typescript/src/types.d.ts.map +1 -1
  145. package/lib/typescript/src/useComponent.d.ts +1 -1
  146. package/lib/typescript/src/useComponent.d.ts.map +1 -1
  147. package/lib/typescript/src/useIsFocused.d.ts.map +1 -1
  148. package/lib/typescript/src/useNavigationBuilder.d.ts +1 -1
  149. package/lib/typescript/src/useNavigationBuilder.d.ts.map +1 -1
  150. package/lib/typescript/src/useNavigationState.d.ts.map +1 -1
  151. package/package.json +30 -12
  152. package/src/StaticNavigation.tsx +48 -34
  153. package/src/types.tsx +33 -12
  154. package/src/useIsFocused.tsx +20 -31
  155. package/src/useNavigationBuilder.tsx +3 -1
  156. package/src/useNavigationState.tsx +15 -17
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@react-navigation/core",
3
3
  "description": "Core utilities for building navigators",
4
- "version": "7.0.0-rc.0",
4
+ "version": "7.0.0-rc.10",
5
5
  "keywords": [
6
6
  "react",
7
7
  "react-native",
@@ -17,11 +17,17 @@
17
17
  "url": "https://github.com/react-navigation/react-navigation/issues"
18
18
  },
19
19
  "homepage": "https://reactnavigation.org",
20
- "main": "lib/commonjs/index.js",
21
- "react-native": "src/index.tsx",
22
- "source": "src/index.tsx",
23
- "module": "lib/module/index.js",
24
- "types": "lib/typescript/src/index.d.ts",
20
+ "source": "./src/index.tsx",
21
+ "main": "./lib/commonjs/index.js",
22
+ "module": "./lib/module/index.js",
23
+ "types": "./lib/typescript/src/index.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./lib/typescript/src/index.d.ts",
27
+ "import": "./lib/module/index.js",
28
+ "require": "./lib/commonjs/index.js"
29
+ }
30
+ },
25
31
  "files": [
26
32
  "src",
27
33
  "lib",
@@ -35,21 +41,23 @@
35
41
  "clean": "del lib"
36
42
  },
37
43
  "dependencies": {
38
- "@react-navigation/routers": "^7.0.0-rc.0",
44
+ "@react-navigation/routers": "^7.0.0-rc.6",
39
45
  "escape-string-regexp": "^4.0.0",
40
46
  "nanoid": "3.3.7",
41
47
  "query-string": "^7.1.3",
42
48
  "react-is": "^18.2.0",
43
- "use-latest-callback": "^0.1.9"
49
+ "use-latest-callback": "^0.2.1",
50
+ "use-sync-external-store": "^1.2.2"
44
51
  },
45
52
  "devDependencies": {
46
53
  "@testing-library/react-native": "^12.4.3",
47
54
  "@types/react": "~18.2.79",
48
55
  "@types/react-is": "^18.2.3",
56
+ "@types/use-sync-external-store": "^0.0.6",
49
57
  "del-cli": "^5.1.0",
50
58
  "immer": "^10.0.3",
51
59
  "react": "18.2.0",
52
- "react-native-builder-bob": "^0.23.2",
60
+ "react-native-builder-bob": "^0.26.0",
53
61
  "react-test-renderer": "18.2.0",
54
62
  "typescript": "^5.5.2"
55
63
  },
@@ -60,8 +68,18 @@
60
68
  "source": "src",
61
69
  "output": "lib",
62
70
  "targets": [
63
- "commonjs",
64
- "module",
71
+ [
72
+ "commonjs",
73
+ {
74
+ "esm": true
75
+ }
76
+ ],
77
+ [
78
+ "module",
79
+ {
80
+ "esm": true
81
+ }
82
+ ],
65
83
  [
66
84
  "typescript",
67
85
  {
@@ -70,5 +88,5 @@
70
88
  ]
71
89
  ]
72
90
  },
73
- "gitHead": "2a1d67089eea2a3d87e38a870ccee35a79c55d7d"
91
+ "gitHead": "d801b91d2aea4bf10852b03ea31836c0e5cb9442"
74
92
  }
@@ -93,10 +93,7 @@ type StaticRouteConfig<
93
93
  EventMap extends EventMapBase,
94
94
  Navigation,
95
95
  > = RouteConfigProps<
96
- // FIXME: the param list is inferred from the screen component
97
- // So we can't use the type here
98
- // Fallback to ParamListBase for now
99
- ParamListBase,
96
+ ParamList,
100
97
  string,
101
98
  State,
102
99
  ScreenOptions,
@@ -404,31 +401,39 @@ export function createComponentForStaticNavigation(
404
401
  );
405
402
  }
406
403
 
407
- const items = screens ? getItemsFromScreens(Screen, screens) : [];
404
+ const items: (() => JSX.Element | null)[] = [];
408
405
 
409
- if (groups) {
410
- items.push(
411
- ...Object.entries(groups).map(([key, { if: useIf, ...group }]) => {
412
- const groupItems = getItemsFromScreens(Screen, group.screens);
406
+ // Loop through the config to find screens and groups
407
+ // So we add the screens and groups in the same order as they are defined
408
+ for (const key in config) {
409
+ if (key === 'screens' && screens) {
410
+ items.push(...getItemsFromScreens(Screen, screens));
411
+ }
413
412
 
414
- return () => {
415
- // Call unconditionally since screen configs may contain `useIf` hooks
416
- const children = groupItems.map((item) => item());
413
+ if (key === 'groups' && groups) {
414
+ items.push(
415
+ ...Object.entries(groups).map(([key, { if: useIf, ...group }]) => {
416
+ const groupItems = getItemsFromScreens(Screen, group.screens);
417
417
 
418
- const shouldRender = useIf == null || useIf();
418
+ return () => {
419
+ // Call unconditionally since screen configs may contain `useIf` hooks
420
+ const children = groupItems.map((item) => item());
419
421
 
420
- if (!shouldRender) {
421
- return null;
422
- }
422
+ const shouldRender = useIf == null || useIf();
423
423
 
424
- return (
425
- <Group navigationKey={key} {...group} key={key}>
426
- {children}
427
- </Group>
428
- );
429
- };
430
- })
431
- );
424
+ if (!shouldRender) {
425
+ return null;
426
+ }
427
+
428
+ return (
429
+ <Group navigationKey={key} {...group} key={key}>
430
+ {children}
431
+ </Group>
432
+ );
433
+ };
434
+ })
435
+ );
436
+ }
432
437
  }
433
438
 
434
439
  const NavigatorComponent = () => {
@@ -594,23 +599,32 @@ export function createPathConfigForStaticNavigation(
594
599
  );
595
600
  };
596
601
 
597
- const screens = t.config.screens
598
- ? createPathConfigForScreens(
599
- t.config.screens,
600
- o?.initialRouteName ?? t.config.initialRouteName
601
- )
602
- : {};
602
+ const screens = {};
603
603
 
604
- if (t.config.groups) {
605
- Object.entries(t.config.groups).forEach(([, group]) => {
604
+ // Loop through the config to find screens and groups
605
+ // So we add the screens and groups in the same order as they are defined
606
+ for (const key in t.config) {
607
+ if (key === 'screens' && t.config.screens) {
606
608
  Object.assign(
607
609
  screens,
608
610
  createPathConfigForScreens(
609
- group.screens,
611
+ t.config.screens,
610
612
  o?.initialRouteName ?? t.config.initialRouteName
611
613
  )
612
614
  );
613
- });
615
+ }
616
+
617
+ if (key === 'groups' && t.config.groups) {
618
+ Object.entries(t.config.groups).forEach(([, group]) => {
619
+ Object.assign(
620
+ screens,
621
+ createPathConfigForScreens(
622
+ group.screens,
623
+ o?.initialRouteName ?? t.config.initialRouteName
624
+ )
625
+ );
626
+ });
627
+ }
614
628
  }
615
629
 
616
630
  if (Object.keys(screens).length === 0) {
package/src/types.tsx CHANGED
@@ -122,7 +122,7 @@ export type EventMapCore<State extends NavigationState> = {
122
122
  };
123
123
 
124
124
  export type EventArg<
125
- EventName extends string,
125
+ EventName,
126
126
  CanPreventDefault extends boolean | undefined = false,
127
127
  Data = undefined,
128
128
  > = {
@@ -150,10 +150,13 @@ export type EventArg<
150
150
  export type EventListenerCallback<
151
151
  EventMap extends EventMapBase,
152
152
  EventName extends keyof EventMap,
153
+ EventCanPreventDefault extends
154
+ | boolean
155
+ | undefined = EventMap[EventName]['canPreventDefault'],
153
156
  > = (
154
157
  e: EventArg<
155
- Extract<EventName, string>,
156
- EventMap[EventName]['canPreventDefault'],
158
+ EventName,
159
+ undefined extends EventCanPreventDefault ? false : EventCanPreventDefault,
157
160
  EventMap[EventName]['data']
158
161
  >
159
162
  ) => void;
@@ -722,12 +725,16 @@ export type RouteGroupConfig<
722
725
  * Layout for the screens inside the group.
723
726
  * This will override the `screenLayout` of parent group or navigator.
724
727
  */
725
- screenLayout?: (props: {
726
- route: RouteProp<ParamList, keyof ParamList>;
727
- navigation: Navigation;
728
- theme: ReactNavigation.Theme;
729
- children: React.ReactElement;
730
- }) => React.ReactElement;
728
+ screenLayout?:
729
+ | ((props: {
730
+ route: RouteProp<ParamList, keyof ParamList>;
731
+ navigation: Navigation;
732
+ theme: ReactNavigation.Theme;
733
+ children: React.ReactElement;
734
+ }) => React.ReactElement)
735
+ | {
736
+ // FIXME: TypeScript doesn't seem to infer `navigation` correctly without this
737
+ };
731
738
 
732
739
  /**
733
740
  * Children React Elements to extract the route configuration from.
@@ -775,6 +782,20 @@ export type NavigationContainerEventMap = {
775
782
  };
776
783
  };
777
784
 
785
+ type NotUndefined<T> = T extends undefined ? never : T;
786
+
787
+ export type ParamListRoute<ParamList extends ParamListBase> = {
788
+ [RouteName in keyof ParamList]: NavigatorScreenParams<{}> extends ParamList[RouteName]
789
+ ? NotUndefined<ParamList[RouteName]> extends NavigatorScreenParams<infer T>
790
+ ? ParamListRoute<T>
791
+ : Route<Extract<RouteName, string>, ParamList[RouteName]>
792
+ : Route<Extract<RouteName, string>, ParamList[RouteName]>;
793
+ }[keyof ParamList];
794
+
795
+ type MaybeParamListRoute<ParamList extends {}> = ParamList extends ParamListBase
796
+ ? ParamListRoute<ParamList>
797
+ : Route<string>;
798
+
778
799
  export type NavigationContainerRef<ParamList extends {}> =
779
800
  NavigationHelpers<ParamList> &
780
801
  EventConsumer<NavigationContainerEventMap> & {
@@ -791,7 +812,7 @@ export type NavigationContainerRef<ParamList extends {}> =
791
812
  /**
792
813
  * Get the currently focused navigation route.
793
814
  */
794
- getCurrentRoute(): Route<string> | undefined;
815
+ getCurrentRoute(): MaybeParamListRoute<ParamList> | undefined;
795
816
  /**
796
817
  * Get the currently focused route's options.
797
818
  */
@@ -838,11 +859,11 @@ export type TypeBag<
838
859
  };
839
860
 
840
861
  export type NavigatorTypeBagBase = {
841
- ParamList: ParamListBase;
862
+ ParamList: {};
842
863
  NavigatorID: string | undefined;
843
864
  State: NavigationState;
844
865
  ScreenOptions: {};
845
- EventMap: EventMapBase;
866
+ EventMap: {};
846
867
  NavigationList: NavigationListBase<ParamListBase>;
847
868
  Navigator: React.ComponentType<any>;
848
869
  };
@@ -1,5 +1,4 @@
1
1
  import * as React from 'react';
2
- import { useState } from 'react';
3
2
 
4
3
  import { useNavigation } from './useNavigation';
5
4
 
@@ -9,35 +8,25 @@ import { useNavigation } from './useNavigation';
9
8
  */
10
9
  export function useIsFocused(): boolean {
11
10
  const navigation = useNavigation();
12
- const [isFocused, setIsFocused] = useState(navigation.isFocused);
13
11
 
14
- const valueToReturn = navigation.isFocused();
15
-
16
- if (isFocused !== valueToReturn) {
17
- // If the value has changed since the last render, we need to update it.
18
- // This could happen if we missed an update from the event listeners during re-render.
19
- // React will process this update immediately, so the old subscription value won't be committed.
20
- // It is still nice to avoid returning a mismatched value though, so let's override the return value.
21
- // This is the same logic as in https://github.com/facebook/react/tree/master/packages/use-subscription
22
- setIsFocused(valueToReturn);
23
- }
24
-
25
- React.useEffect(() => {
26
- const unsubscribeFocus = navigation.addListener('focus', () =>
27
- setIsFocused(true)
28
- );
29
-
30
- const unsubscribeBlur = navigation.addListener('blur', () =>
31
- setIsFocused(false)
32
- );
33
-
34
- return () => {
35
- unsubscribeFocus();
36
- unsubscribeBlur();
37
- };
38
- }, [navigation]);
39
-
40
- React.useDebugValue(valueToReturn);
41
-
42
- return valueToReturn;
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
+ );
24
+
25
+ const value = React.useSyncExternalStore(
26
+ subscribe,
27
+ navigation.isFocused,
28
+ navigation.isFocused
29
+ );
30
+
31
+ return value;
43
32
  }
@@ -132,7 +132,9 @@ const getRouteConfigsFromChildren = <
132
132
  : groupOptions != null
133
133
  ? [...groupOptions, child.props.screenOptions]
134
134
  : [child.props.screenOptions],
135
- child.props.screenLayout ?? groupLayout
135
+ typeof child.props.screenLayout === 'function'
136
+ ? child.props.screenLayout
137
+ : groupLayout
136
138
  )
137
139
  );
138
140
  return acc;
@@ -1,5 +1,6 @@
1
1
  import type { NavigationState, ParamListBase } from '@react-navigation/routers';
2
2
  import * as React from 'react';
3
+ import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector';
3
4
 
4
5
  import type { NavigationProp } from './types';
5
6
  import { useNavigation } from './useNavigation';
@@ -18,24 +19,21 @@ export function useNavigationState<ParamList extends ParamListBase, T>(
18
19
  ): T {
19
20
  const navigation = useNavigation<NavigationProp<ParamList>>();
20
21
 
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()));
22
+ const subscribe = React.useCallback(
23
+ (callback: () => void) => {
24
+ const unsubscribe = navigation.addListener('state', callback);
24
25
 
25
- // We store the selector in a ref to avoid re-subscribing listeners every render
26
- const selectorRef = React.useRef(selector);
26
+ return unsubscribe;
27
+ },
28
+ [navigation]
29
+ );
27
30
 
28
- React.useEffect(() => {
29
- selectorRef.current = selector;
30
- });
31
+ const value = useSyncExternalStoreWithSelector(
32
+ subscribe,
33
+ navigation.getState,
34
+ navigation.getState,
35
+ selector
36
+ );
31
37
 
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());
38
+ return value;
41
39
  }