@react-navigation/core 8.0.0-alpha.30 → 8.0.0-alpha.32
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.
- package/lib/module/BaseNavigationContainer.js +132 -82
- package/lib/module/BaseNavigationContainer.js.map +1 -1
- package/lib/module/DataLoading.js +3 -1
- package/lib/module/DataLoading.js.map +1 -1
- package/lib/module/NavigationBuilderContext.js +2 -1
- package/lib/module/NavigationBuilderContext.js.map +1 -1
- package/lib/module/NavigationIndependentTree.js +21 -11
- package/lib/module/NavigationIndependentTree.js.map +1 -1
- package/lib/module/NavigationProvider.js +10 -1
- package/lib/module/NavigationProvider.js.map +1 -1
- package/lib/module/NavigationRootContext.js +8 -0
- package/lib/module/NavigationRootContext.js.map +1 -0
- package/lib/module/NavigationStateContext.js +3 -0
- package/lib/module/NavigationStateContext.js.map +1 -1
- package/lib/module/SceneView.js +3 -1
- package/lib/module/SceneView.js.map +1 -1
- package/lib/module/StaticNavigation.js +54 -19
- package/lib/module/StaticNavigation.js.map +1 -1
- package/lib/module/createNavigationContainerRef.js +1 -1
- package/lib/module/createNavigationContainerRef.js.map +1 -1
- package/lib/module/findFocusedRoute.js.map +1 -1
- package/lib/module/getActionFromState.js.map +1 -1
- package/lib/module/getStateFromPath.js +15 -16
- package/lib/module/getStateFromPath.js.map +1 -1
- package/lib/module/getStateFromRouteParams.js +0 -1
- package/lib/module/getStateFromRouteParams.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/internal.js +2 -0
- package/lib/module/internal.js.map +1 -0
- package/lib/module/types.js +0 -1
- package/lib/module/types.js.map +1 -1
- package/lib/module/useDescriptors.js +6 -4
- package/lib/module/useDescriptors.js.map +1 -1
- package/lib/module/useKeyedChildListeners.js +1 -0
- package/lib/module/useKeyedChildListeners.js.map +1 -1
- package/lib/module/useNavigation.js +2 -2
- package/lib/module/useNavigation.js.map +1 -1
- package/lib/module/useNavigationBuilder.js +14 -4
- package/lib/module/useNavigationBuilder.js.map +1 -1
- package/lib/module/useNavigationCache.js +23 -31
- package/lib/module/useNavigationCache.js.map +1 -1
- package/lib/module/useNavigationHelpers.js +18 -37
- package/lib/module/useNavigationHelpers.js.map +1 -1
- package/lib/module/useNavigationState.js +85 -33
- package/lib/module/useNavigationState.js.map +1 -1
- package/lib/module/useOnGetNavigation.js +26 -0
- package/lib/module/useOnGetNavigation.js.map +1 -0
- package/lib/module/useSyncState.js +25 -6
- package/lib/module/useSyncState.js.map +1 -1
- package/lib/typescript/src/BaseNavigationContainer.d.ts.map +1 -1
- package/lib/typescript/src/DataLoading.d.ts.map +1 -1
- package/lib/typescript/src/NavigationBuilderContext.d.ts +4 -1
- package/lib/typescript/src/NavigationBuilderContext.d.ts.map +1 -1
- package/lib/typescript/src/NavigationIndependentTree.d.ts.map +1 -1
- package/lib/typescript/src/NavigationProvider.d.ts +9 -5
- package/lib/typescript/src/NavigationProvider.d.ts.map +1 -1
- package/lib/typescript/src/NavigationRootContext.d.ts +8 -0
- package/lib/typescript/src/NavigationRootContext.d.ts.map +1 -0
- package/lib/typescript/src/NavigationStateContext.d.ts +1 -0
- package/lib/typescript/src/NavigationStateContext.d.ts.map +1 -1
- package/lib/typescript/src/SceneView.d.ts +2 -1
- package/lib/typescript/src/SceneView.d.ts.map +1 -1
- package/lib/typescript/src/StaticNavigation.d.ts.map +1 -1
- package/lib/typescript/src/createNavigationContainerRef.d.ts.map +1 -1
- package/lib/typescript/src/findFocusedRoute.d.ts +3 -8
- package/lib/typescript/src/findFocusedRoute.d.ts.map +1 -1
- package/lib/typescript/src/getActionFromState.d.ts.map +1 -1
- package/lib/typescript/src/getStateFromPath.d.ts +1 -4
- package/lib/typescript/src/getStateFromPath.d.ts.map +1 -1
- package/lib/typescript/src/getStateFromRouteParams.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/internal.d.ts +3 -0
- package/lib/typescript/src/internal.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +3 -6
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useDescriptors.d.ts +2 -1
- package/lib/typescript/src/useDescriptors.d.ts.map +1 -1
- package/lib/typescript/src/useKeyedChildListeners.d.ts +1 -0
- package/lib/typescript/src/useKeyedChildListeners.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationBuilder.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationCache.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationHelpers.d.ts +1 -2
- package/lib/typescript/src/useNavigationHelpers.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationState.d.ts +7 -2
- package/lib/typescript/src/useNavigationState.d.ts.map +1 -1
- package/lib/typescript/src/useOnGetNavigation.d.ts +12 -0
- package/lib/typescript/src/useOnGetNavigation.d.ts.map +1 -0
- package/lib/typescript/src/useSyncState.d.ts +1 -0
- package/lib/typescript/src/useSyncState.d.ts.map +1 -1
- package/package.json +11 -5
- package/src/BaseNavigationContainer.tsx +194 -97
- package/src/DataLoading.tsx +4 -1
- package/src/NavigationBuilderContext.tsx +10 -1
- package/src/NavigationIndependentTree.tsx +27 -16
- package/src/NavigationProvider.tsx +13 -6
- package/src/NavigationRootContext.tsx +11 -0
- package/src/NavigationStateContext.tsx +4 -0
- package/src/SceneView.tsx +4 -0
- package/src/StaticNavigation.tsx +77 -19
- package/src/createNavigationContainerRef.tsx +0 -2
- package/src/findFocusedRoute.tsx +7 -12
- package/src/getActionFromState.tsx +2 -1
- package/src/getStateFromPath.tsx +31 -43
- package/src/getStateFromRouteParams.tsx +0 -1
- package/src/index.tsx +1 -0
- package/src/internal.tsx +2 -0
- package/src/types.tsx +3 -7
- package/src/useDescriptors.tsx +6 -3
- package/src/useKeyedChildListeners.tsx +1 -0
- package/src/useNavigation.tsx +2 -2
- package/src/useNavigationBuilder.tsx +14 -4
- package/src/useNavigationCache.tsx +24 -33
- package/src/useNavigationHelpers.tsx +19 -38
- package/src/useNavigationState.tsx +104 -31
- package/src/useOnGetNavigation.tsx +29 -0
- package/src/useSyncState.tsx +27 -6
- package/lib/module/checkSerializable.js +0 -51
- package/lib/module/checkSerializable.js.map +0 -1
- package/lib/typescript/src/checkSerializable.d.ts +0 -14
- package/lib/typescript/src/checkSerializable.d.ts.map +0 -1
- package/src/checkSerializable.tsx +0 -90
package/src/StaticNavigation.tsx
CHANGED
|
@@ -678,6 +678,9 @@ const MemoizedScreen = React.memo(
|
|
|
678
678
|
|
|
679
679
|
MemoizedScreen.displayName = 'Memo(Screen)';
|
|
680
680
|
|
|
681
|
+
const hasPropertyGetter = (object: object, property: PropertyKey) =>
|
|
682
|
+
Object.getOwnPropertyDescriptor(object, property)?.get != null;
|
|
683
|
+
|
|
681
684
|
const getItemsFromScreens = (
|
|
682
685
|
Screen: React.ComponentType<any>,
|
|
683
686
|
screens: StaticConfigScreens<any, any, any, any, any>
|
|
@@ -688,18 +691,57 @@ const getItemsFromScreens = (
|
|
|
688
691
|
let useIf: (() => boolean) | undefined;
|
|
689
692
|
|
|
690
693
|
let isNavigator = false;
|
|
694
|
+
let getComponent: (() => React.ComponentType<any>) | undefined;
|
|
691
695
|
|
|
692
696
|
if ('screen' in item) {
|
|
693
|
-
|
|
697
|
+
if (hasPropertyGetter(item, 'screen')) {
|
|
698
|
+
const rest: Record<string, unknown> = {};
|
|
699
|
+
|
|
700
|
+
// Iterate over the keys to avoid triggering the getter for 'screen'
|
|
701
|
+
for (const key of Object.keys(item)) {
|
|
702
|
+
if (key === 'screen' || key === 'if') {
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
rest[key] = Reflect.get(item, key);
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
useIf = item.if;
|
|
710
|
+
props = rest;
|
|
694
711
|
|
|
695
|
-
|
|
696
|
-
|
|
712
|
+
getComponent = () => {
|
|
713
|
+
const screen = item.screen;
|
|
697
714
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
715
|
+
if (isValidElementType(screen)) {
|
|
716
|
+
return screen;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
if (
|
|
720
|
+
screen != null &&
|
|
721
|
+
typeof screen === 'object' &&
|
|
722
|
+
'config' in screen
|
|
723
|
+
) {
|
|
724
|
+
throw new Error(
|
|
725
|
+
`Got a navigator object for the screen '${name}' instead of a component. A navigator cannot be specified when using a getter.`
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
throw new Error(
|
|
730
|
+
`Got an invalid screen component for the screen '${name}'. This can happen if you passed 'undefined'. You likely forgot to export your component from the file it's defined in, or mixed up default import and named import when importing.`
|
|
731
|
+
);
|
|
732
|
+
};
|
|
733
|
+
} else {
|
|
734
|
+
const { screen, if: _if, ...rest } = item;
|
|
735
|
+
|
|
736
|
+
useIf = _if;
|
|
737
|
+
props = rest;
|
|
738
|
+
|
|
739
|
+
if (isValidElementType(screen)) {
|
|
740
|
+
component = screen;
|
|
741
|
+
} else if ('config' in screen) {
|
|
742
|
+
isNavigator = true;
|
|
743
|
+
component = screen.getComponent();
|
|
744
|
+
}
|
|
703
745
|
}
|
|
704
746
|
} else if (isValidElementType(item)) {
|
|
705
747
|
component = item;
|
|
@@ -708,18 +750,29 @@ const getItemsFromScreens = (
|
|
|
708
750
|
component = item.getComponent();
|
|
709
751
|
}
|
|
710
752
|
|
|
711
|
-
|
|
753
|
+
let children: (() => React.JSX.Element) | undefined;
|
|
754
|
+
|
|
755
|
+
if (getComponent != null) {
|
|
756
|
+
let element: React.JSX.Element | undefined;
|
|
757
|
+
|
|
758
|
+
children = () =>
|
|
759
|
+
(element ??= <MemoizedScreen component={getComponent()} />);
|
|
760
|
+
} else if (component != null) {
|
|
761
|
+
const element = isNavigator ? (
|
|
762
|
+
React.createElement(component, {})
|
|
763
|
+
) : (
|
|
764
|
+
<MemoizedScreen component={component} />
|
|
765
|
+
);
|
|
766
|
+
|
|
767
|
+
children = () => element;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
if (children == null) {
|
|
712
771
|
throw new Error(
|
|
713
772
|
`Couldn't find a 'screen' property for the screen '${name}'. This can happen if you passed 'undefined'. You likely forgot to export your component from the file it's defined in, or mixed up default import and named import when importing.`
|
|
714
773
|
);
|
|
715
774
|
}
|
|
716
775
|
|
|
717
|
-
const element = isNavigator ? (
|
|
718
|
-
React.createElement(component, {})
|
|
719
|
-
) : (
|
|
720
|
-
<MemoizedScreen component={component} />
|
|
721
|
-
);
|
|
722
|
-
|
|
723
776
|
return () => {
|
|
724
777
|
const shouldRender = useIf == null || useIf();
|
|
725
778
|
|
|
@@ -729,7 +782,7 @@ const getItemsFromScreens = (
|
|
|
729
782
|
|
|
730
783
|
return (
|
|
731
784
|
<Screen key={name} name={name} {...props}>
|
|
732
|
-
{
|
|
785
|
+
{children}
|
|
733
786
|
</Screen>
|
|
734
787
|
);
|
|
735
788
|
};
|
|
@@ -895,7 +948,7 @@ type PathConfigForStaticNavigation = Omit<
|
|
|
895
948
|
// Mark screens that resolve to the same pattern and same component or navigator
|
|
896
949
|
const markSharedPathConfigs = (
|
|
897
950
|
screens: PathConfigMapForStaticNavigation,
|
|
898
|
-
sources: WeakMap<PathConfigForStaticNavigation,
|
|
951
|
+
sources: WeakMap<PathConfigForStaticNavigation, ScreenForPathConfig>,
|
|
899
952
|
blocked: WeakSet<PathConfigForStaticNavigation>
|
|
900
953
|
) => {
|
|
901
954
|
const candidates = new Map<string, PathConfigForStaticNavigation[]>();
|
|
@@ -992,7 +1045,7 @@ export function createPathConfigForStaticNavigation<ParamList extends {}>(
|
|
|
992
1045
|
const blocked = new WeakSet<PathConfigForStaticNavigation>();
|
|
993
1046
|
const sources = new WeakMap<
|
|
994
1047
|
PathConfigForStaticNavigation,
|
|
995
|
-
|
|
1048
|
+
ScreenForPathConfig
|
|
996
1049
|
>();
|
|
997
1050
|
|
|
998
1051
|
const createPathConfigForTree = (
|
|
@@ -1043,7 +1096,11 @@ export function createPathConfigForStaticNavigation<ParamList extends {}>(
|
|
|
1043
1096
|
|
|
1044
1097
|
sources.set(
|
|
1045
1098
|
screenConfig,
|
|
1046
|
-
typeof item === 'object' &&
|
|
1099
|
+
typeof item === 'object' &&
|
|
1100
|
+
'screen' in item &&
|
|
1101
|
+
!hasPropertyGetter(item, 'screen')
|
|
1102
|
+
? item.screen
|
|
1103
|
+
: item
|
|
1047
1104
|
);
|
|
1048
1105
|
|
|
1049
1106
|
const normalizePath = (path: string) =>
|
|
@@ -1129,6 +1186,7 @@ export function createPathConfigForStaticNavigation<ParamList extends {}>(
|
|
|
1129
1186
|
!hasExplicitScreens &&
|
|
1130
1187
|
!hasDisabledLinking &&
|
|
1131
1188
|
'screen' in item &&
|
|
1189
|
+
!hasPropertyGetter(item, 'screen') &&
|
|
1132
1190
|
'config' in item.screen &&
|
|
1133
1191
|
(item.screen.config.screens || item.screen.config.groups)
|
|
1134
1192
|
) {
|
package/src/findFocusedRoute.tsx
CHANGED
|
@@ -1,19 +1,14 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { NavigationState, PartialState } from '@react-navigation/routers';
|
|
2
2
|
|
|
3
|
-
type
|
|
4
|
-
| {
|
|
5
|
-
key?: string | undefined;
|
|
6
|
-
name: string;
|
|
7
|
-
params?: object | undefined;
|
|
8
|
-
path?: string | undefined;
|
|
9
|
-
}
|
|
10
|
-
| undefined;
|
|
3
|
+
type State = NavigationState | PartialState<NavigationState>;
|
|
11
4
|
|
|
12
|
-
export function findFocusedRoute(
|
|
13
|
-
|
|
5
|
+
export function findFocusedRoute(
|
|
6
|
+
state: State
|
|
7
|
+
): State['routes'][number] | undefined {
|
|
8
|
+
let current: State | undefined = state;
|
|
14
9
|
|
|
15
10
|
while (current != null) {
|
|
16
|
-
const route:
|
|
11
|
+
const route: State['routes'][number] | undefined =
|
|
17
12
|
current.routes[current.index ?? current.routes.length - 1];
|
|
18
13
|
|
|
19
14
|
if (route?.state == null) {
|
|
@@ -89,7 +89,8 @@ export function getActionFromState(
|
|
|
89
89
|
return undefined;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
let current: PartialState<NavigationState> | undefined =
|
|
92
|
+
let current: NavigationState | PartialState<NavigationState> | undefined =
|
|
93
|
+
route.state;
|
|
93
94
|
let config: ConfigItem | undefined = normalizedConfig?.screens?.[route.name];
|
|
94
95
|
let params = { ...route.params } as NavigatorScreenParams<ParamListBase>;
|
|
95
96
|
|
package/src/getStateFromPath.tsx
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
InitialState,
|
|
3
|
-
NavigationState,
|
|
4
|
-
PartialState,
|
|
5
|
-
} from '@react-navigation/routers';
|
|
1
|
+
import type { NavigationState, PartialState } from '@react-navigation/routers';
|
|
6
2
|
import escape from 'escape-string-regexp';
|
|
7
3
|
import queryString from 'query-string';
|
|
8
4
|
|
|
9
5
|
import { arrayStartsWith } from './arrayStartsWith';
|
|
10
|
-
import { findFocusedRoute } from './findFocusedRoute';
|
|
11
6
|
import {
|
|
12
7
|
combinePatternParts,
|
|
13
8
|
getPatternParts,
|
|
@@ -58,13 +53,10 @@ type InitialRouteConfig = {
|
|
|
58
53
|
parentScreens: string[];
|
|
59
54
|
};
|
|
60
55
|
|
|
61
|
-
type ResultState = PartialState<NavigationState> & {
|
|
62
|
-
state?: ResultState | undefined;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
56
|
type ParsedRoute = {
|
|
66
57
|
name: string;
|
|
67
58
|
params?: Record<string, unknown> | undefined;
|
|
59
|
+
path?: string | undefined;
|
|
68
60
|
};
|
|
69
61
|
|
|
70
62
|
type RoutePatternPart = PatternPart & { screen: string };
|
|
@@ -177,7 +169,7 @@ export function getStateFromPath<ParamList extends {}>(
|
|
|
177
169
|
path: string,
|
|
178
170
|
options?: Options<ParamList>,
|
|
179
171
|
previous?: NavigationState
|
|
180
|
-
):
|
|
172
|
+
): PartialState<NavigationState> | undefined {
|
|
181
173
|
const {
|
|
182
174
|
initialRoutes,
|
|
183
175
|
configs,
|
|
@@ -1016,7 +1008,7 @@ const createStateObject = (
|
|
|
1016
1008
|
initialRoute: string | undefined,
|
|
1017
1009
|
route: ParsedRoute,
|
|
1018
1010
|
isEmpty: boolean
|
|
1019
|
-
):
|
|
1011
|
+
): PartialState<NavigationState> => {
|
|
1020
1012
|
if (isEmpty) {
|
|
1021
1013
|
if (initialRoute) {
|
|
1022
1014
|
return {
|
|
@@ -1047,7 +1039,32 @@ const createNestedStateObject = (
|
|
|
1047
1039
|
routes: ParsedRoute[],
|
|
1048
1040
|
initialRoutes: InitialRouteConfig[],
|
|
1049
1041
|
routeConfig?: RouteConfig
|
|
1050
|
-
):
|
|
1042
|
+
): PartialState<NavigationState> | undefined => {
|
|
1043
|
+
const focusedRoute = routes[routes.length - 1];
|
|
1044
|
+
|
|
1045
|
+
if (focusedRoute == null) {
|
|
1046
|
+
return undefined;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
focusedRoute.path = path.replace(/\/$/, '');
|
|
1050
|
+
|
|
1051
|
+
const queryParams = parseQueryParams(
|
|
1052
|
+
path,
|
|
1053
|
+
routeConfig?.parse,
|
|
1054
|
+
routeConfig?.pathParamNames,
|
|
1055
|
+
routeConfig?.explicitParamNames,
|
|
1056
|
+
routeConfig?.hasNestedScreens,
|
|
1057
|
+
focusedRoute.params
|
|
1058
|
+
);
|
|
1059
|
+
|
|
1060
|
+
if (!queryParams.valid) {
|
|
1061
|
+
return undefined;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
if (queryParams.params) {
|
|
1065
|
+
focusedRoute.params = { ...focusedRoute.params, ...queryParams.params };
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1051
1068
|
let route = routes.shift();
|
|
1052
1069
|
|
|
1053
1070
|
if (route == null) {
|
|
@@ -1060,11 +1077,7 @@ const createNestedStateObject = (
|
|
|
1060
1077
|
|
|
1061
1078
|
parentScreens.push(route.name);
|
|
1062
1079
|
|
|
1063
|
-
const state
|
|
1064
|
-
initialRoute,
|
|
1065
|
-
route,
|
|
1066
|
-
routes.length === 0
|
|
1067
|
-
);
|
|
1080
|
+
const state = createStateObject(initialRoute, route, routes.length === 0);
|
|
1068
1081
|
|
|
1069
1082
|
if (routes.length > 0) {
|
|
1070
1083
|
let nestedState = state;
|
|
@@ -1104,31 +1117,6 @@ const createNestedStateObject = (
|
|
|
1104
1117
|
}
|
|
1105
1118
|
}
|
|
1106
1119
|
|
|
1107
|
-
const focusedRoute = findFocusedRoute(state);
|
|
1108
|
-
|
|
1109
|
-
if (focusedRoute == null) {
|
|
1110
|
-
return undefined;
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
focusedRoute.path = path.replace(/\/$/, '');
|
|
1114
|
-
|
|
1115
|
-
const queryParams = parseQueryParams(
|
|
1116
|
-
path,
|
|
1117
|
-
routeConfig?.parse,
|
|
1118
|
-
routeConfig?.pathParamNames,
|
|
1119
|
-
routeConfig?.explicitParamNames,
|
|
1120
|
-
routeConfig?.hasNestedScreens,
|
|
1121
|
-
focusedRoute.params
|
|
1122
|
-
);
|
|
1123
|
-
|
|
1124
|
-
if (!queryParams.valid) {
|
|
1125
|
-
return undefined;
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
if (queryParams.params) {
|
|
1129
|
-
focusedRoute.params = { ...focusedRoute.params, ...queryParams.params };
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
1120
|
return state;
|
|
1133
1121
|
};
|
|
1134
1122
|
|
package/src/index.tsx
CHANGED
|
@@ -19,6 +19,7 @@ export { NavigationHelpersContext } from './NavigationHelpersContext';
|
|
|
19
19
|
export { NavigationIndependentTree } from './NavigationIndependentTree';
|
|
20
20
|
export { NavigationMetaContext } from './NavigationMetaContext';
|
|
21
21
|
export {
|
|
22
|
+
IsScreenContext,
|
|
22
23
|
NavigationContext,
|
|
23
24
|
NavigationProvider,
|
|
24
25
|
NavigationRouteContext,
|
package/src/internal.tsx
ADDED
package/src/types.tsx
CHANGED
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
} from '@react-navigation/routers';
|
|
11
11
|
import type * as React from 'react';
|
|
12
12
|
|
|
13
|
+
import type { Theme as InternalTheme } from './internal';
|
|
13
14
|
import type {
|
|
14
15
|
FlatType,
|
|
15
16
|
KeyOf,
|
|
@@ -51,8 +52,7 @@ export interface RootNavigator {}
|
|
|
51
52
|
* }
|
|
52
53
|
* ```
|
|
53
54
|
*/
|
|
54
|
-
|
|
55
|
-
export interface Theme {}
|
|
55
|
+
export interface Theme extends InternalTheme {}
|
|
56
56
|
|
|
57
57
|
export type RootParamList =
|
|
58
58
|
RootNavigator extends PrivateValueStore<
|
|
@@ -1360,7 +1360,7 @@ type NavigationListForGroups<ParentList, Groups> = Groups extends {}
|
|
|
1360
1360
|
|
|
1361
1361
|
export type NavigationContainerRef<ParamList extends {}> = Omit<
|
|
1362
1362
|
NavigationHelpers<ParamList>,
|
|
1363
|
-
keyof NavigationHelpersRoute<{}>
|
|
1363
|
+
keyof NavigationHelpersRoute<{}> | 'isFocused'
|
|
1364
1364
|
> &
|
|
1365
1365
|
NavigationHelpersRoute<{}> &
|
|
1366
1366
|
EventConsumer<NavigationContainerEventMap> & {
|
|
@@ -1386,10 +1386,6 @@ export type NavigationContainerRef<ParamList extends {}> = Omit<
|
|
|
1386
1386
|
* Whether the navigation container is ready to handle actions.
|
|
1387
1387
|
*/
|
|
1388
1388
|
isReady(): boolean;
|
|
1389
|
-
/**
|
|
1390
|
-
* Stub function for setOptions on navigation object for use with useNavigation.
|
|
1391
|
-
*/
|
|
1392
|
-
setOptions(): never;
|
|
1393
1389
|
};
|
|
1394
1390
|
|
|
1395
1391
|
export type NavigationContainerRefWithCurrent<ParamList extends {}> =
|
package/src/useDescriptors.tsx
CHANGED
|
@@ -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,6 +108,7 @@ export function useDescriptors<
|
|
|
107
108
|
onAction,
|
|
108
109
|
getState,
|
|
109
110
|
setState,
|
|
111
|
+
subscribe,
|
|
110
112
|
addListener,
|
|
111
113
|
addKeyedListener,
|
|
112
114
|
onRouteFocus,
|
|
@@ -123,8 +125,8 @@ export function useDescriptors<
|
|
|
123
125
|
onOptionsChange,
|
|
124
126
|
scheduleUpdate,
|
|
125
127
|
flushUpdates,
|
|
126
|
-
stackRef,
|
|
127
128
|
getIsStateEmitted,
|
|
129
|
+
withStackTrace,
|
|
128
130
|
} = React.use(NavigationBuilderContext);
|
|
129
131
|
|
|
130
132
|
const context = React.useMemo(
|
|
@@ -140,7 +142,7 @@ export function useDescriptors<
|
|
|
140
142
|
getIsStateEmitted,
|
|
141
143
|
scheduleUpdate,
|
|
142
144
|
flushUpdates,
|
|
143
|
-
|
|
145
|
+
withStackTrace,
|
|
144
146
|
}),
|
|
145
147
|
[
|
|
146
148
|
navigation,
|
|
@@ -154,7 +156,7 @@ export function useDescriptors<
|
|
|
154
156
|
getIsStateEmitted,
|
|
155
157
|
scheduleUpdate,
|
|
156
158
|
flushUpdates,
|
|
157
|
-
|
|
159
|
+
withStackTrace,
|
|
158
160
|
]
|
|
159
161
|
);
|
|
160
162
|
|
|
@@ -257,6 +259,7 @@ export function useDescriptors<
|
|
|
257
259
|
routeState={routeState}
|
|
258
260
|
getState={getState}
|
|
259
261
|
setState={setState}
|
|
262
|
+
subscribe={subscribe}
|
|
260
263
|
options={customOptions}
|
|
261
264
|
clearOptions={clearOptions}
|
|
262
265
|
/>
|
package/src/useNavigation.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
-
import { NavigationContainerRefContext } from './NavigationContainerRefContext';
|
|
4
3
|
import { NavigationContext } from './NavigationProvider';
|
|
4
|
+
import { NavigationRootContext } from './NavigationRootContext';
|
|
5
5
|
import type {
|
|
6
6
|
GenericNavigation,
|
|
7
7
|
NavigationListForNavigator,
|
|
@@ -30,7 +30,7 @@ export function useNavigation<
|
|
|
30
30
|
keyof NavigationListForNested<Navigator>,
|
|
31
31
|
>(name: RouteName): NavigationListForNested<Navigator>[RouteName];
|
|
32
32
|
export function useNavigation(name?: string): unknown {
|
|
33
|
-
const root = React.use(
|
|
33
|
+
const root = React.use(NavigationRootContext);
|
|
34
34
|
const navigation = React.use(NavigationContext);
|
|
35
35
|
|
|
36
36
|
if (name === undefined) {
|
|
@@ -22,7 +22,7 @@ import { isArrayEqual } from './isArrayEqual';
|
|
|
22
22
|
import { NavigationBuilderContext } from './NavigationBuilderContext';
|
|
23
23
|
import { NavigationHelpersContext } from './NavigationHelpersContext';
|
|
24
24
|
import { NavigationMetaContext } from './NavigationMetaContext';
|
|
25
|
-
import { NavigationRouteContext } from './NavigationProvider';
|
|
25
|
+
import { IsScreenContext, NavigationRouteContext } from './NavigationProvider';
|
|
26
26
|
import { NavigationStateContext } from './NavigationStateContext';
|
|
27
27
|
import { PreventRemoveProvider } from './PreventRemoveProvider';
|
|
28
28
|
import { Screen } from './Screen';
|
|
@@ -47,6 +47,7 @@ import { useLazyValue } from './useLazyValue';
|
|
|
47
47
|
import { useNavigationHelpers } from './useNavigationHelpers';
|
|
48
48
|
import { NavigationStateListenerProvider } from './useNavigationState';
|
|
49
49
|
import { useOnAction } from './useOnAction';
|
|
50
|
+
import { useOnGetNavigation } from './useOnGetNavigation';
|
|
50
51
|
import { useOnGetState } from './useOnGetState';
|
|
51
52
|
import { useOnRouteFocus } from './useOnRouteFocus';
|
|
52
53
|
import { useRegisterNavigator } from './useRegisterNavigator';
|
|
@@ -453,6 +454,7 @@ export function useNavigationBuilder<
|
|
|
453
454
|
state: currentState,
|
|
454
455
|
getState: getCurrentState,
|
|
455
456
|
setState: setCurrentState,
|
|
457
|
+
subscribe,
|
|
456
458
|
setKey,
|
|
457
459
|
getKey,
|
|
458
460
|
getIsInitial,
|
|
@@ -1004,7 +1006,6 @@ export function useNavigationBuilder<
|
|
|
1004
1006
|
onAction,
|
|
1005
1007
|
onUnhandledAction,
|
|
1006
1008
|
getState,
|
|
1007
|
-
state,
|
|
1008
1009
|
emitter,
|
|
1009
1010
|
router,
|
|
1010
1011
|
});
|
|
@@ -1019,6 +1020,8 @@ export function useNavigationBuilder<
|
|
|
1019
1020
|
getStateListeners: keyedListeners.getState,
|
|
1020
1021
|
});
|
|
1021
1022
|
|
|
1023
|
+
useOnGetNavigation({ navigation });
|
|
1024
|
+
|
|
1022
1025
|
const descriptors = useDescriptors<
|
|
1023
1026
|
State,
|
|
1024
1027
|
ActionHelpers,
|
|
@@ -1033,6 +1036,7 @@ export function useNavigationBuilder<
|
|
|
1033
1036
|
onAction,
|
|
1034
1037
|
getState,
|
|
1035
1038
|
setState,
|
|
1039
|
+
subscribe,
|
|
1036
1040
|
onRouteFocus,
|
|
1037
1041
|
addListener,
|
|
1038
1042
|
addKeyedListener,
|
|
@@ -1062,11 +1066,17 @@ export function useNavigationBuilder<
|
|
|
1062
1066
|
<NavigationMetaContext.Provider value={undefined}>
|
|
1063
1067
|
<NavigationHelpersContext.Provider value={navigation}>
|
|
1064
1068
|
<NavigationStateListenerProvider
|
|
1069
|
+
isSynced={!shouldUpdate}
|
|
1065
1070
|
state={state}
|
|
1066
|
-
getState={
|
|
1071
|
+
getState={getState}
|
|
1072
|
+
subscribe={subscribe}
|
|
1067
1073
|
>
|
|
1068
1074
|
<FocusedRouteKeyContext.Provider value={focusedRoute.key}>
|
|
1069
|
-
<PreventRemoveProvider>
|
|
1075
|
+
<PreventRemoveProvider>
|
|
1076
|
+
<IsScreenContext.Provider value={false}>
|
|
1077
|
+
{element}
|
|
1078
|
+
</IsScreenContext.Provider>
|
|
1079
|
+
</PreventRemoveProvider>
|
|
1070
1080
|
</FocusedRouteKeyContext.Provider>
|
|
1071
1081
|
</NavigationStateListenerProvider>
|
|
1072
1082
|
</NavigationHelpersContext.Provider>
|
|
@@ -72,8 +72,9 @@ export function useNavigationCache<
|
|
|
72
72
|
router,
|
|
73
73
|
emitter,
|
|
74
74
|
}: Options<State, ScreenOptions, EventMap>) {
|
|
75
|
-
const
|
|
76
|
-
|
|
75
|
+
const parentNavigation = React.use(NavigationContext);
|
|
76
|
+
|
|
77
|
+
const { withStackTrace } = React.use(NavigationBuilderContext);
|
|
77
78
|
|
|
78
79
|
// Cache object which holds navigation objects for each screen
|
|
79
80
|
// We use `React.useMemo` instead of `React.useRef` coz we want to invalidate it when deps change
|
|
@@ -88,7 +89,7 @@ export function useNavigationCache<
|
|
|
88
89
|
>,
|
|
89
90
|
}),
|
|
90
91
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
91
|
-
[getState,
|
|
92
|
+
[getState, parentNavigation, navigation, setOptions, emitter]
|
|
92
93
|
);
|
|
93
94
|
|
|
94
95
|
const next = routes.reduce<
|
|
@@ -100,34 +101,12 @@ export function useNavigationCache<
|
|
|
100
101
|
// If a cached navigation object already exists, reuse it
|
|
101
102
|
acc[route.key] = previous;
|
|
102
103
|
} else {
|
|
103
|
-
const withStack = (callback: () => void) => {
|
|
104
|
-
let isStackSet = false;
|
|
105
|
-
|
|
106
|
-
try {
|
|
107
|
-
if (
|
|
108
|
-
process.env.NODE_ENV !== 'production' &&
|
|
109
|
-
stackRef &&
|
|
110
|
-
!stackRef.current
|
|
111
|
-
) {
|
|
112
|
-
// Capture the stack trace for devtools
|
|
113
|
-
stackRef.current = new Error().stack;
|
|
114
|
-
isStackSet = true;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
callback();
|
|
118
|
-
} finally {
|
|
119
|
-
if (isStackSet && stackRef) {
|
|
120
|
-
stackRef.current = undefined;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
|
|
125
104
|
const dispatch = (
|
|
126
105
|
thunk:
|
|
127
106
|
| NavigationAction
|
|
128
107
|
| ((state: State) => NavigationAction | null | undefined)
|
|
129
108
|
) => {
|
|
130
|
-
|
|
109
|
+
withStackTrace(dispatch, () => {
|
|
131
110
|
React.startTransition(() => {
|
|
132
111
|
const action =
|
|
133
112
|
typeof thunk === 'function' ? thunk(getState()) : thunk;
|
|
@@ -135,8 +114,8 @@ export function useNavigationCache<
|
|
|
135
114
|
if (action != null) {
|
|
136
115
|
navigation.dispatch({ source: route.key, ...action });
|
|
137
116
|
}
|
|
138
|
-
})
|
|
139
|
-
);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
140
119
|
};
|
|
141
120
|
|
|
142
121
|
const actions = {
|
|
@@ -146,9 +125,13 @@ export function useNavigationCache<
|
|
|
146
125
|
|
|
147
126
|
const helpers = Object.keys(actions).reduce<Record<string, () => void>>(
|
|
148
127
|
(acc, name) => {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
128
|
+
const helper = (...args: any) =>
|
|
129
|
+
withStackTrace(helper, () =>
|
|
130
|
+
// @ts-expect-error: name is a valid key, but TypeScript is dumb
|
|
131
|
+
dispatch(actions[name](...args))
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
acc[name] = helper;
|
|
152
135
|
|
|
153
136
|
return acc;
|
|
154
137
|
},
|
|
@@ -172,10 +155,18 @@ export function useNavigationCache<
|
|
|
172
155
|
}
|
|
173
156
|
|
|
174
157
|
if (routeName !== undefined) {
|
|
175
|
-
|
|
158
|
+
const parent = parentNavigation?.getParent(routeName);
|
|
159
|
+
|
|
160
|
+
if (parent === undefined) {
|
|
161
|
+
throw new Error(
|
|
162
|
+
`Couldn't find a navigation object for '${routeName}' in current or any parent screens. Is your component inside the correct screen?`
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return parent;
|
|
176
167
|
}
|
|
177
168
|
|
|
178
|
-
return
|
|
169
|
+
return parentNavigation;
|
|
179
170
|
},
|
|
180
171
|
setOptions: (options: Partial<ScreenOptions>) => {
|
|
181
172
|
setOptions((o) => ({
|