@react-navigation/core 6.2.2 → 6.4.0
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/README.md +17 -11
- package/lib/commonjs/BaseNavigationContainer.js.map +1 -1
- package/lib/commonjs/PreventRemoveContext.js +17 -0
- package/lib/commonjs/PreventRemoveContext.js.map +1 -0
- package/lib/commonjs/PreventRemoveProvider.js +114 -0
- package/lib/commonjs/PreventRemoveProvider.js.map +1 -0
- package/lib/commonjs/getStateFromPath.js +1 -1
- package/lib/commonjs/getStateFromPath.js.map +1 -1
- package/lib/commonjs/index.js +36 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/useComponent.js +22 -12
- package/lib/commonjs/useComponent.js.map +1 -1
- package/lib/commonjs/useEventEmitter.js +1 -1
- package/lib/commonjs/useEventEmitter.js.map +1 -1
- package/lib/commonjs/useFocusEffect.js +1 -1
- package/lib/commonjs/useFocusEffect.js.map +1 -1
- package/lib/commonjs/useKeyedChildListeners.js +2 -2
- package/lib/commonjs/useKeyedChildListeners.js.map +1 -1
- package/lib/commonjs/useNavigationBuilder.js +4 -2
- package/lib/commonjs/useNavigationBuilder.js.map +1 -1
- package/lib/commonjs/usePreventRemove.js +59 -0
- package/lib/commonjs/usePreventRemove.js.map +1 -0
- package/lib/commonjs/usePreventRemoveContext.js +27 -0
- package/lib/commonjs/usePreventRemoveContext.js.map +1 -0
- package/lib/module/BaseNavigationContainer.js.map +1 -1
- package/lib/module/PreventRemoveContext.js +9 -0
- package/lib/module/PreventRemoveContext.js.map +1 -0
- package/lib/module/PreventRemoveProvider.js +96 -0
- package/lib/module/PreventRemoveProvider.js.map +1 -0
- package/lib/module/getStateFromPath.js +1 -1
- package/lib/module/getStateFromPath.js.map +1 -1
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/module/useComponent.js +23 -12
- package/lib/module/useComponent.js.map +1 -1
- package/lib/module/useEventEmitter.js +1 -1
- package/lib/module/useEventEmitter.js.map +1 -1
- package/lib/module/useFocusEffect.js +1 -1
- package/lib/module/useFocusEffect.js.map +1 -1
- package/lib/module/useKeyedChildListeners.js +2 -2
- package/lib/module/useKeyedChildListeners.js.map +1 -1
- package/lib/module/useNavigationBuilder.js +3 -2
- package/lib/module/useNavigationBuilder.js.map +1 -1
- package/lib/module/usePreventRemove.js +41 -0
- package/lib/module/usePreventRemove.js.map +1 -0
- package/lib/module/usePreventRemoveContext.js +12 -0
- package/lib/module/usePreventRemoveContext.js.map +1 -0
- package/lib/typescript/src/PreventRemoveContext.d.ts +13 -0
- package/lib/typescript/src/PreventRemoveProvider.d.ts +9 -0
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/types.d.ts +10 -6
- package/lib/typescript/src/useComponent.d.ts +5 -1
- package/lib/typescript/src/useDescriptors.d.ts +3 -3
- package/lib/typescript/src/useNavigationBuilder.d.ts +9 -7
- package/lib/typescript/src/useNavigationHelpers.d.ts +3 -3
- package/lib/typescript/src/usePreventRemove.d.ts +12 -0
- package/lib/typescript/src/usePreventRemoveContext.d.ts +4 -0
- package/package.json +10 -8
- package/src/BaseNavigationContainer.tsx +1 -1
- package/src/PreventRemoveContext.tsx +21 -0
- package/src/PreventRemoveProvider.tsx +126 -0
- package/src/getStateFromPath.tsx +4 -1
- package/src/index.tsx +4 -0
- package/src/types.tsx +39 -14
- package/src/useComponent.tsx +19 -12
- package/src/useEventEmitter.tsx +3 -1
- package/src/useFocusEffect.tsx +1 -1
- package/src/useKeyedChildListeners.tsx +6 -4
- package/src/useNavigationBuilder.tsx +9 -5
- package/src/usePreventRemove.tsx +51 -0
- package/src/usePreventRemoveContext.tsx +15 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["usePreventRemoveContext.tsx"],"names":["React","PreventRemoveContext","usePreventRemoveContext","value","useContext","Error"],"mappings":"AAAA,OAAO,KAAKA,KAAZ,MAAuB,OAAvB;AAEA,OAAOC,oBAAP,MAAiC,wBAAjC;AAEA,eAAe,SAASC,uBAAT,GAAmC;AAChD,QAAMC,KAAK,GAAGH,KAAK,CAACI,UAAN,CAAiBH,oBAAjB,CAAd;;AAEA,MAAIE,KAAK,IAAI,IAAb,EAAmB;AACjB,UAAM,IAAIE,KAAJ,CACJ,uFADI,CAAN;AAGD;;AAED,SAAOF,KAAP;AACD","sourcesContent":["import * as React from 'react';\n\nimport PreventRemoveContext from './PreventRemoveContext';\n\nexport default function usePreventRemoveContext() {\n const value = React.useContext(PreventRemoveContext);\n\n if (value == null) {\n throw new Error(\n \"Couldn't find the prevent remove context. Is your component inside NavigationContent?\"\n );\n }\n\n return value;\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* A type of an object that have a route key as an object key
|
|
4
|
+
* and a value whether to prevent that route.
|
|
5
|
+
*/
|
|
6
|
+
export declare type PreventedRoutes = Record<string, {
|
|
7
|
+
preventRemove: boolean;
|
|
8
|
+
}>;
|
|
9
|
+
declare const PreventRemoveContext: React.Context<{
|
|
10
|
+
preventedRoutes: PreventedRoutes;
|
|
11
|
+
setPreventRemove: (id: string, routeKey: string, preventRemove: boolean) => void;
|
|
12
|
+
} | undefined>;
|
|
13
|
+
export default PreventRemoveContext;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
declare type Props = {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Component used for managing which routes have to be prevented from removal in native-stack.
|
|
7
|
+
*/
|
|
8
|
+
export default function PreventRemoveProvider({ children }: Props): JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -11,6 +11,8 @@ export { default as NavigationContainerRefContext } from './NavigationContainerR
|
|
|
11
11
|
export { default as NavigationContext } from './NavigationContext';
|
|
12
12
|
export { default as NavigationHelpersContext } from './NavigationHelpersContext';
|
|
13
13
|
export { default as NavigationRouteContext } from './NavigationRouteContext';
|
|
14
|
+
export { default as PreventRemoveContext } from './PreventRemoveContext';
|
|
15
|
+
export { default as PreventRemoveProvider } from './PreventRemoveProvider';
|
|
14
16
|
export * from './types';
|
|
15
17
|
export { default as useFocusEffect } from './useFocusEffect';
|
|
16
18
|
export { default as useIsFocused } from './useIsFocused';
|
|
@@ -18,6 +20,8 @@ export { default as useNavigation } from './useNavigation';
|
|
|
18
20
|
export { default as useNavigationBuilder } from './useNavigationBuilder';
|
|
19
21
|
export { default as useNavigationContainerRef } from './useNavigationContainerRef';
|
|
20
22
|
export { default as useNavigationState } from './useNavigationState';
|
|
23
|
+
export { default as UNSTABLE_usePreventRemove } from './usePreventRemove';
|
|
24
|
+
export { default as usePreventRemoveContext } from './usePreventRemoveContext';
|
|
21
25
|
export { default as useRoute } from './useRoute';
|
|
22
26
|
export { default as validatePathConfig } from './validatePathConfig';
|
|
23
27
|
export * from '@react-navigation/routers';
|
|
@@ -142,13 +142,13 @@ declare type NavigationHelpersCommon<ParamList extends ParamListBase, State exte
|
|
|
142
142
|
* @param name Name of the route to navigate to.
|
|
143
143
|
* @param [params] Params object for the route.
|
|
144
144
|
*/
|
|
145
|
-
navigate<RouteName extends keyof ParamList>(...args: undefined extends ParamList[RouteName] ? [screen: RouteName] | [screen: RouteName, params: ParamList[RouteName]] : [screen: RouteName, params: ParamList[RouteName]]): void;
|
|
145
|
+
navigate<RouteName extends keyof ParamList>(...args: RouteName extends unknown ? undefined extends ParamList[RouteName] ? [screen: RouteName] | [screen: RouteName, params: ParamList[RouteName]] : [screen: RouteName, params: ParamList[RouteName]] : never): void;
|
|
146
146
|
/**
|
|
147
147
|
* Navigate to a route in current navigation tree.
|
|
148
148
|
*
|
|
149
149
|
* @param route Object with `key` or `name` for the route to navigate to, and a `params` object.
|
|
150
150
|
*/
|
|
151
|
-
navigate<RouteName extends keyof ParamList>(options: {
|
|
151
|
+
navigate<RouteName extends keyof ParamList>(options: RouteName extends unknown ? {
|
|
152
152
|
key: string;
|
|
153
153
|
params?: ParamList[RouteName];
|
|
154
154
|
merge?: boolean;
|
|
@@ -157,7 +157,7 @@ declare type NavigationHelpersCommon<ParamList extends ParamListBase, State exte
|
|
|
157
157
|
key?: string;
|
|
158
158
|
params: ParamList[RouteName];
|
|
159
159
|
merge?: boolean;
|
|
160
|
-
}): void;
|
|
160
|
+
} : never): void;
|
|
161
161
|
/**
|
|
162
162
|
* Reset the navigation state to the provided state.
|
|
163
163
|
*
|
|
@@ -247,7 +247,7 @@ export declare type NavigationProp<ParamList extends {}, RouteName extends keyof
|
|
|
247
247
|
*
|
|
248
248
|
* @param params Params object for the current route.
|
|
249
249
|
*/
|
|
250
|
-
setParams(params: Partial<ParamList[RouteName]>): void;
|
|
250
|
+
setParams(params: ParamList[RouteName] extends undefined ? undefined : Partial<ParamList[RouteName]>): void;
|
|
251
251
|
/**
|
|
252
252
|
* Update the options for the route.
|
|
253
253
|
* The options object will be shallow merged with default options object.
|
|
@@ -316,18 +316,22 @@ export declare type Descriptor<ScreenOptions extends {}, Navigation extends Navi
|
|
|
316
316
|
export declare type ScreenListeners<State extends NavigationState, EventMap extends EventMapBase> = Partial<{
|
|
317
317
|
[EventName in keyof (EventMap & EventMapCore<State>)]: EventListenerCallback<EventMap, EventName>;
|
|
318
318
|
}>;
|
|
319
|
+
declare type ScreenComponentType<ParamList extends ParamListBase, RouteName extends keyof ParamList> = React.ComponentType<{
|
|
320
|
+
route: RouteProp<ParamList, RouteName>;
|
|
321
|
+
navigation: any;
|
|
322
|
+
}> | React.ComponentType<{}>;
|
|
319
323
|
export declare type RouteConfigComponent<ParamList extends ParamListBase, RouteName extends keyof ParamList> = {
|
|
320
324
|
/**
|
|
321
325
|
* React component to render for this screen.
|
|
322
326
|
*/
|
|
323
|
-
component:
|
|
327
|
+
component: ScreenComponentType<ParamList, RouteName>;
|
|
324
328
|
getComponent?: never;
|
|
325
329
|
children?: never;
|
|
326
330
|
} | {
|
|
327
331
|
/**
|
|
328
332
|
* Lazily get a React component to render for this screen.
|
|
329
333
|
*/
|
|
330
|
-
getComponent: () =>
|
|
334
|
+
getComponent: () => ScreenComponentType<ParamList, RouteName>;
|
|
331
335
|
component?: never;
|
|
332
336
|
children?: never;
|
|
333
337
|
} | {
|
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
|
|
2
|
+
declare type Render = (children: React.ReactNode) => JSX.Element;
|
|
3
|
+
export default function useComponent(render: Render): ({ children }: {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
}) => JSX.Element;
|
|
6
|
+
export {};
|
|
@@ -50,8 +50,8 @@ export default function useDescriptors<State extends NavigationState, ActionHelp
|
|
|
50
50
|
source?: string | undefined;
|
|
51
51
|
target?: string | undefined;
|
|
52
52
|
}>)): void;
|
|
53
|
-
navigate<RouteName extends string>(...args: [screen: RouteName] | [screen: RouteName, params: object | undefined]): void;
|
|
54
|
-
navigate<RouteName_1 extends string>(options: {
|
|
53
|
+
navigate<RouteName extends string>(...args: RouteName extends unknown ? [screen: RouteName] | [screen: RouteName, params: object | undefined] : never): void;
|
|
54
|
+
navigate<RouteName_1 extends string>(options: RouteName_1 extends unknown ? {
|
|
55
55
|
key: string;
|
|
56
56
|
params?: object | undefined;
|
|
57
57
|
merge?: boolean | undefined;
|
|
@@ -60,7 +60,7 @@ export default function useDescriptors<State extends NavigationState, ActionHelp
|
|
|
60
60
|
key?: string | undefined;
|
|
61
61
|
params: object | undefined;
|
|
62
62
|
merge?: boolean | undefined;
|
|
63
|
-
}): void;
|
|
63
|
+
} : never): void;
|
|
64
64
|
reset(state: State | import("@react-navigation/routers").PartialState<State>): void;
|
|
65
65
|
goBack(): void;
|
|
66
66
|
isFocused(): boolean;
|
|
@@ -38,8 +38,8 @@ export default function useNavigationBuilder<State extends NavigationState, Rout
|
|
|
38
38
|
source?: string | undefined;
|
|
39
39
|
target?: string | undefined;
|
|
40
40
|
}>)): void;
|
|
41
|
-
navigate<RouteName extends string>(...args: [screen: RouteName] | [screen: RouteName, params: object | undefined]): void;
|
|
42
|
-
navigate<RouteName_1 extends string>(options: {
|
|
41
|
+
navigate<RouteName extends string>(...args: RouteName extends unknown ? [screen: RouteName] | [screen: RouteName, params: object | undefined] : never): void;
|
|
42
|
+
navigate<RouteName_1 extends string>(options: RouteName_1 extends unknown ? {
|
|
43
43
|
key: string;
|
|
44
44
|
params?: object | undefined;
|
|
45
45
|
merge?: boolean | undefined;
|
|
@@ -48,7 +48,7 @@ export default function useNavigationBuilder<State extends NavigationState, Rout
|
|
|
48
48
|
key?: string | undefined;
|
|
49
49
|
params: object | undefined;
|
|
50
50
|
merge?: boolean | undefined;
|
|
51
|
-
}): void;
|
|
51
|
+
} : never): void;
|
|
52
52
|
reset(state: Readonly<{
|
|
53
53
|
key: string;
|
|
54
54
|
index: number;
|
|
@@ -119,8 +119,8 @@ export default function useNavigationBuilder<State extends NavigationState, Rout
|
|
|
119
119
|
source?: string | undefined;
|
|
120
120
|
target?: string | undefined;
|
|
121
121
|
}>)): void;
|
|
122
|
-
navigate<RouteName extends string>(...args: [screen: RouteName] | [screen: RouteName, params: object | undefined]): void;
|
|
123
|
-
navigate<RouteName_1 extends string>(options: {
|
|
122
|
+
navigate<RouteName extends string>(...args: RouteName extends unknown ? [screen: RouteName] | [screen: RouteName, params: object | undefined] : never): void;
|
|
123
|
+
navigate<RouteName_1 extends string>(options: RouteName_1 extends unknown ? {
|
|
124
124
|
key: string;
|
|
125
125
|
params?: object | undefined;
|
|
126
126
|
merge?: boolean | undefined;
|
|
@@ -129,7 +129,7 @@ export default function useNavigationBuilder<State extends NavigationState, Rout
|
|
|
129
129
|
key?: string | undefined;
|
|
130
130
|
params: object | undefined;
|
|
131
131
|
merge?: boolean | undefined;
|
|
132
|
-
}): void;
|
|
132
|
+
} : never): void;
|
|
133
133
|
reset(state: State | PartialState<State>): void;
|
|
134
134
|
goBack(): void;
|
|
135
135
|
isFocused(): boolean;
|
|
@@ -158,5 +158,7 @@ export default function useNavigationBuilder<State extends NavigationState, Rout
|
|
|
158
158
|
setParams(params: Partial<object | undefined>): void;
|
|
159
159
|
setOptions(options: Partial<ScreenOptions>): void;
|
|
160
160
|
} & import("./types").EventConsumer<EventMap & EventMapCore<State>> & PrivateValueStore<[ParamListBase, string, EventMap]> & ActionHelpers, import("./types").RouteProp<ParamListBase, string>>>;
|
|
161
|
-
NavigationContent: (
|
|
161
|
+
NavigationContent: ({ children }: {
|
|
162
|
+
children: React.ReactNode;
|
|
163
|
+
}) => JSX.Element;
|
|
162
164
|
};
|
|
@@ -40,8 +40,8 @@ export default function useNavigationHelpers<State extends NavigationState, Acti
|
|
|
40
40
|
source?: string | undefined;
|
|
41
41
|
target?: string | undefined;
|
|
42
42
|
}>)): void;
|
|
43
|
-
navigate<RouteName extends string>(...args: [screen: RouteName] | [screen: RouteName, params: object | undefined]): void;
|
|
44
|
-
navigate<RouteName_1 extends string>(options: {
|
|
43
|
+
navigate<RouteName extends string>(...args: RouteName extends unknown ? [screen: RouteName] | [screen: RouteName, params: object | undefined] : never): void;
|
|
44
|
+
navigate<RouteName_1 extends string>(options: RouteName_1 extends unknown ? {
|
|
45
45
|
key: string;
|
|
46
46
|
params?: object | undefined;
|
|
47
47
|
merge?: boolean | undefined;
|
|
@@ -50,7 +50,7 @@ export default function useNavigationHelpers<State extends NavigationState, Acti
|
|
|
50
50
|
key?: string | undefined;
|
|
51
51
|
params: object | undefined;
|
|
52
52
|
merge?: boolean | undefined;
|
|
53
|
-
}): void;
|
|
53
|
+
} : never): void;
|
|
54
54
|
reset(state: Readonly<{
|
|
55
55
|
key: string;
|
|
56
56
|
index: number;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { NavigationAction } from '@react-navigation/routers';
|
|
2
|
+
/**
|
|
3
|
+
* Hook to prevent screen from being removed. Can be used to prevent users from leaving the screen.
|
|
4
|
+
*
|
|
5
|
+
* @param preventRemove Boolean indicating whether to prevent screen from being removed.
|
|
6
|
+
* @param callback Function which is executed when screen was prevented from being removed.
|
|
7
|
+
*/
|
|
8
|
+
export default function usePreventRemove(preventRemove: boolean, callback: (options: {
|
|
9
|
+
data: {
|
|
10
|
+
action: NavigationAction;
|
|
11
|
+
};
|
|
12
|
+
}) => void): void;
|
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": "6.
|
|
4
|
+
"version": "6.4.0",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
7
7
|
"react-native",
|
|
@@ -31,25 +31,26 @@
|
|
|
31
31
|
"access": "public"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
|
-
"
|
|
34
|
+
"prepack": "bob build",
|
|
35
35
|
"clean": "del lib"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@react-navigation/routers": "^6.1.
|
|
38
|
+
"@react-navigation/routers": "^6.1.3",
|
|
39
39
|
"escape-string-regexp": "^4.0.0",
|
|
40
40
|
"nanoid": "^3.1.23",
|
|
41
41
|
"query-string": "^7.0.0",
|
|
42
|
-
"react-is": "^16.13.0"
|
|
42
|
+
"react-is": "^16.13.0",
|
|
43
|
+
"use-latest-callback": "^0.1.5"
|
|
43
44
|
},
|
|
44
45
|
"devDependencies": {
|
|
45
46
|
"@testing-library/react-native": "^7.2.0",
|
|
46
|
-
"@types/react": "
|
|
47
|
+
"@types/react": "~18.0.0",
|
|
47
48
|
"@types/react-is": "^17.0.0",
|
|
48
49
|
"del-cli": "^3.0.1",
|
|
49
50
|
"immer": "^9.0.2",
|
|
50
|
-
"react": "
|
|
51
|
+
"react": "18.0.0",
|
|
51
52
|
"react-native-builder-bob": "^0.18.1",
|
|
52
|
-
"react-test-renderer": "
|
|
53
|
+
"react-test-renderer": "18.0.0",
|
|
53
54
|
"typescript": "^4.7.4"
|
|
54
55
|
},
|
|
55
56
|
"peerDependencies": {
|
|
@@ -68,5 +69,6 @@
|
|
|
68
69
|
}
|
|
69
70
|
]
|
|
70
71
|
]
|
|
71
|
-
}
|
|
72
|
+
},
|
|
73
|
+
"gitHead": "fc4c3a63ab156e17db7ba0cbd32ada319f78714e"
|
|
72
74
|
}
|
|
@@ -230,7 +230,7 @@ const BaseNavigationContainer = React.forwardRef(
|
|
|
230
230
|
const lastEmittedOptionsRef = React.useRef<object | undefined>();
|
|
231
231
|
|
|
232
232
|
const onOptionsChange = React.useCallback(
|
|
233
|
-
(options) => {
|
|
233
|
+
(options: object) => {
|
|
234
234
|
if (lastEmittedOptionsRef.current === options) {
|
|
235
235
|
return;
|
|
236
236
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A type of an object that have a route key as an object key
|
|
5
|
+
* and a value whether to prevent that route.
|
|
6
|
+
*/
|
|
7
|
+
export type PreventedRoutes = Record<string, { preventRemove: boolean }>;
|
|
8
|
+
|
|
9
|
+
const PreventRemoveContext = React.createContext<
|
|
10
|
+
| {
|
|
11
|
+
preventedRoutes: PreventedRoutes;
|
|
12
|
+
setPreventRemove: (
|
|
13
|
+
id: string,
|
|
14
|
+
routeKey: string,
|
|
15
|
+
preventRemove: boolean
|
|
16
|
+
) => void;
|
|
17
|
+
}
|
|
18
|
+
| undefined
|
|
19
|
+
>(undefined);
|
|
20
|
+
|
|
21
|
+
export default PreventRemoveContext;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { nanoid } from 'nanoid/non-secure';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import useLatestCallback from 'use-latest-callback';
|
|
4
|
+
|
|
5
|
+
import NavigationHelpersContext from './NavigationHelpersContext';
|
|
6
|
+
import NavigationRouteContext from './NavigationRouteContext';
|
|
7
|
+
import PreventRemoveContext, { PreventedRoutes } from './PreventRemoveContext';
|
|
8
|
+
|
|
9
|
+
type Props = {
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type PreventedRoutesMap = Map<
|
|
14
|
+
string,
|
|
15
|
+
{
|
|
16
|
+
routeKey: string;
|
|
17
|
+
preventRemove: boolean;
|
|
18
|
+
}
|
|
19
|
+
>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Util function to transform map of prevented routes to a simpler object.
|
|
23
|
+
*/
|
|
24
|
+
const transformPreventedRoutes = (
|
|
25
|
+
preventedRoutesMap: PreventedRoutesMap
|
|
26
|
+
): PreventedRoutes => {
|
|
27
|
+
const preventedRoutesToTransform = [...preventedRoutesMap.values()];
|
|
28
|
+
|
|
29
|
+
const preventedRoutes = preventedRoutesToTransform.reduce<PreventedRoutes>(
|
|
30
|
+
(acc, { routeKey, preventRemove }) => {
|
|
31
|
+
acc[routeKey] = {
|
|
32
|
+
preventRemove: acc[routeKey]?.preventRemove || preventRemove,
|
|
33
|
+
};
|
|
34
|
+
return acc;
|
|
35
|
+
},
|
|
36
|
+
{}
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
return preventedRoutes;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Component used for managing which routes have to be prevented from removal in native-stack.
|
|
44
|
+
*/
|
|
45
|
+
export default function PreventRemoveProvider({ children }: Props) {
|
|
46
|
+
const [parentId] = React.useState(() => nanoid());
|
|
47
|
+
const [preventedRoutesMap, setPreventedRoutesMap] =
|
|
48
|
+
React.useState<PreventedRoutesMap>(new Map());
|
|
49
|
+
|
|
50
|
+
const navigation = React.useContext(NavigationHelpersContext);
|
|
51
|
+
const route = React.useContext(NavigationRouteContext);
|
|
52
|
+
|
|
53
|
+
const preventRemoveContextValue = React.useContext(PreventRemoveContext);
|
|
54
|
+
// take `setPreventRemove` from parent context - if exist it means we're in a nested context
|
|
55
|
+
const setParentPrevented = preventRemoveContextValue?.setPreventRemove;
|
|
56
|
+
|
|
57
|
+
const setPreventRemove = useLatestCallback(
|
|
58
|
+
(id: string, routeKey: string, preventRemove: boolean): void => {
|
|
59
|
+
if (
|
|
60
|
+
preventRemove &&
|
|
61
|
+
(navigation == null ||
|
|
62
|
+
navigation
|
|
63
|
+
?.getState()
|
|
64
|
+
.routes.every((route) => route.key !== routeKey))
|
|
65
|
+
) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`Couldn't find a route with the key ${routeKey}. Is your component inside NavigationContent?`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
setPreventedRoutesMap((prevPrevented) => {
|
|
72
|
+
// values haven't changed - do nothing
|
|
73
|
+
if (
|
|
74
|
+
routeKey === prevPrevented.get(id)?.routeKey &&
|
|
75
|
+
preventRemove === prevPrevented.get(id)?.preventRemove
|
|
76
|
+
) {
|
|
77
|
+
return prevPrevented;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const nextPrevented = new Map(prevPrevented);
|
|
81
|
+
|
|
82
|
+
if (preventRemove) {
|
|
83
|
+
nextPrevented.set(id, {
|
|
84
|
+
routeKey,
|
|
85
|
+
preventRemove,
|
|
86
|
+
});
|
|
87
|
+
} else {
|
|
88
|
+
nextPrevented.delete(id);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return nextPrevented;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const isPrevented = [...preventedRoutesMap.values()].some(
|
|
97
|
+
({ preventRemove }) => preventRemove
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
React.useEffect(() => {
|
|
101
|
+
if (route?.key !== undefined && setParentPrevented !== undefined) {
|
|
102
|
+
// when route is defined (and setParentPrevented) it means we're in a nested stack
|
|
103
|
+
// route.key then will be the route key of parent
|
|
104
|
+
setParentPrevented(parentId, route.key, isPrevented);
|
|
105
|
+
return () => {
|
|
106
|
+
setParentPrevented(parentId, route.key, false);
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return;
|
|
111
|
+
}, [parentId, isPrevented, route?.key, setParentPrevented]);
|
|
112
|
+
|
|
113
|
+
const value = React.useMemo(
|
|
114
|
+
() => ({
|
|
115
|
+
setPreventRemove,
|
|
116
|
+
preventedRoutes: transformPreventedRoutes(preventedRoutesMap),
|
|
117
|
+
}),
|
|
118
|
+
[setPreventRemove, preventedRoutesMap]
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<PreventRemoveContext.Provider value={value}>
|
|
123
|
+
{children}
|
|
124
|
+
</PreventRemoveContext.Provider>
|
|
125
|
+
);
|
|
126
|
+
}
|
package/src/getStateFromPath.tsx
CHANGED
|
@@ -565,7 +565,10 @@ const parseQueryParams = (
|
|
|
565
565
|
|
|
566
566
|
if (parseConfig) {
|
|
567
567
|
Object.keys(params).forEach((name) => {
|
|
568
|
-
if (
|
|
568
|
+
if (
|
|
569
|
+
Object.hasOwnProperty.call(parseConfig, name) &&
|
|
570
|
+
typeof params[name] === 'string'
|
|
571
|
+
) {
|
|
569
572
|
params[name] = parseConfig[name](params[name] as string);
|
|
570
573
|
}
|
|
571
574
|
});
|
package/src/index.tsx
CHANGED
|
@@ -11,6 +11,8 @@ export { default as NavigationContainerRefContext } from './NavigationContainerR
|
|
|
11
11
|
export { default as NavigationContext } from './NavigationContext';
|
|
12
12
|
export { default as NavigationHelpersContext } from './NavigationHelpersContext';
|
|
13
13
|
export { default as NavigationRouteContext } from './NavigationRouteContext';
|
|
14
|
+
export { default as PreventRemoveContext } from './PreventRemoveContext';
|
|
15
|
+
export { default as PreventRemoveProvider } from './PreventRemoveProvider';
|
|
14
16
|
export * from './types';
|
|
15
17
|
export { default as useFocusEffect } from './useFocusEffect';
|
|
16
18
|
export { default as useIsFocused } from './useIsFocused';
|
|
@@ -18,6 +20,8 @@ export { default as useNavigation } from './useNavigation';
|
|
|
18
20
|
export { default as useNavigationBuilder } from './useNavigationBuilder';
|
|
19
21
|
export { default as useNavigationContainerRef } from './useNavigationContainerRef';
|
|
20
22
|
export { default as useNavigationState } from './useNavigationState';
|
|
23
|
+
export { default as UNSTABLE_usePreventRemove } from './usePreventRemove';
|
|
24
|
+
export { default as usePreventRemoveContext } from './usePreventRemoveContext';
|
|
21
25
|
export { default as useRoute } from './useRoute';
|
|
22
26
|
export { default as validatePathConfig } from './validatePathConfig';
|
|
23
27
|
export * from '@react-navigation/routers';
|
package/src/types.tsx
CHANGED
|
@@ -192,9 +192,18 @@ type NavigationHelpersCommon<
|
|
|
192
192
|
* @param [params] Params object for the route.
|
|
193
193
|
*/
|
|
194
194
|
navigate<RouteName extends keyof ParamList>(
|
|
195
|
-
...args:
|
|
196
|
-
|
|
197
|
-
|
|
195
|
+
...args: // this first condition allows us to iterate over a union type
|
|
196
|
+
// This is to avoid getting a union of all the params from `ParamList[RouteName]`,
|
|
197
|
+
// which will get our types all mixed up if a union RouteName is passed in.
|
|
198
|
+
RouteName extends unknown
|
|
199
|
+
? // This condition checks if the params are optional,
|
|
200
|
+
// which means it's either undefined or a union with undefined
|
|
201
|
+
undefined extends ParamList[RouteName]
|
|
202
|
+
?
|
|
203
|
+
| [screen: RouteName] // if the params are optional, we don't have to provide it
|
|
204
|
+
| [screen: RouteName, params: ParamList[RouteName]]
|
|
205
|
+
: [screen: RouteName, params: ParamList[RouteName]]
|
|
206
|
+
: never
|
|
198
207
|
): void;
|
|
199
208
|
|
|
200
209
|
/**
|
|
@@ -203,14 +212,16 @@ type NavigationHelpersCommon<
|
|
|
203
212
|
* @param route Object with `key` or `name` for the route to navigate to, and a `params` object.
|
|
204
213
|
*/
|
|
205
214
|
navigate<RouteName extends keyof ParamList>(
|
|
206
|
-
options:
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
215
|
+
options: RouteName extends unknown
|
|
216
|
+
?
|
|
217
|
+
| { key: string; params?: ParamList[RouteName]; merge?: boolean }
|
|
218
|
+
| {
|
|
219
|
+
name: RouteName;
|
|
220
|
+
key?: string;
|
|
221
|
+
params: ParamList[RouteName];
|
|
222
|
+
merge?: boolean;
|
|
223
|
+
}
|
|
224
|
+
: never
|
|
214
225
|
): void;
|
|
215
226
|
|
|
216
227
|
/**
|
|
@@ -325,7 +336,11 @@ export type NavigationProp<
|
|
|
325
336
|
*
|
|
326
337
|
* @param params Params object for the current route.
|
|
327
338
|
*/
|
|
328
|
-
setParams(
|
|
339
|
+
setParams(
|
|
340
|
+
params: ParamList[RouteName] extends undefined
|
|
341
|
+
? undefined
|
|
342
|
+
: Partial<ParamList[RouteName]>
|
|
343
|
+
): void;
|
|
329
344
|
|
|
330
345
|
/**
|
|
331
346
|
* Update the options for the route.
|
|
@@ -436,6 +451,16 @@ export type ScreenListeners<
|
|
|
436
451
|
>;
|
|
437
452
|
}>;
|
|
438
453
|
|
|
454
|
+
type ScreenComponentType<
|
|
455
|
+
ParamList extends ParamListBase,
|
|
456
|
+
RouteName extends keyof ParamList
|
|
457
|
+
> =
|
|
458
|
+
| React.ComponentType<{
|
|
459
|
+
route: RouteProp<ParamList, RouteName>;
|
|
460
|
+
navigation: any;
|
|
461
|
+
}>
|
|
462
|
+
| React.ComponentType<{}>;
|
|
463
|
+
|
|
439
464
|
export type RouteConfigComponent<
|
|
440
465
|
ParamList extends ParamListBase,
|
|
441
466
|
RouteName extends keyof ParamList
|
|
@@ -444,7 +469,7 @@ export type RouteConfigComponent<
|
|
|
444
469
|
/**
|
|
445
470
|
* React component to render for this screen.
|
|
446
471
|
*/
|
|
447
|
-
component:
|
|
472
|
+
component: ScreenComponentType<ParamList, RouteName>;
|
|
448
473
|
getComponent?: never;
|
|
449
474
|
children?: never;
|
|
450
475
|
}
|
|
@@ -452,7 +477,7 @@ export type RouteConfigComponent<
|
|
|
452
477
|
/**
|
|
453
478
|
* Lazily get a React component to render for this screen.
|
|
454
479
|
*/
|
|
455
|
-
getComponent: () =>
|
|
480
|
+
getComponent: () => ScreenComponentType<ParamList, RouteName>;
|
|
456
481
|
component?: never;
|
|
457
482
|
children?: never;
|
|
458
483
|
}
|
package/src/useComponent.tsx
CHANGED
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
type Render = (children: React.ReactNode) => JSX.Element;
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
render: Render;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const NavigationContent = ({ render, children }: Props) => {
|
|
11
|
+
return render(children);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default function useComponent(render: Render) {
|
|
15
|
+
const renderRef = React.useRef<Render | null>(render);
|
|
8
16
|
|
|
9
17
|
// Normally refs shouldn't be mutated in render
|
|
10
18
|
// But we return a component which will be rendered
|
|
11
19
|
// So it's just for immediate consumption
|
|
12
|
-
|
|
20
|
+
renderRef.current = render;
|
|
13
21
|
|
|
14
22
|
React.useEffect(() => {
|
|
15
|
-
|
|
23
|
+
renderRef.current = null;
|
|
16
24
|
});
|
|
17
25
|
|
|
18
|
-
return React.useRef((
|
|
19
|
-
const
|
|
26
|
+
return React.useRef(({ children }: { children: React.ReactNode }) => {
|
|
27
|
+
const render = renderRef.current;
|
|
20
28
|
|
|
21
|
-
if (
|
|
29
|
+
if (render === null) {
|
|
22
30
|
throw new Error(
|
|
23
31
|
'The returned component must be rendered in the same render phase as the hook.'
|
|
24
32
|
);
|
|
25
33
|
}
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
return <Component {...props} {...rest} />;
|
|
35
|
+
return <NavigationContent render={render}>{children}</NavigationContent>;
|
|
29
36
|
}).current;
|
|
30
37
|
}
|
package/src/useEventEmitter.tsx
CHANGED
|
@@ -21,7 +21,9 @@ export default function useEventEmitter<T extends Record<string, any>>(
|
|
|
21
21
|
listenRef.current = listen;
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
-
const listeners = React.useRef<Record<string, Record<string, Listeners>>>(
|
|
24
|
+
const listeners = React.useRef<Record<string, Record<string, Listeners>>>(
|
|
25
|
+
Object.create(null)
|
|
26
|
+
);
|
|
25
27
|
|
|
26
28
|
const create = React.useCallback((target: string) => {
|
|
27
29
|
const removeListener = (type: string, callback: (data: any) => void) => {
|
package/src/useFocusEffect.tsx
CHANGED
|
@@ -52,7 +52,7 @@ export default function useFocusEffect(effect: EffectCallback) {
|
|
|
52
52
|
'Instead, write the async function inside your effect ' +
|
|
53
53
|
'and call it immediately:\n\n' +
|
|
54
54
|
'useFocusEffect(\n' +
|
|
55
|
-
' React.useCallback() => {\n' +
|
|
55
|
+
' React.useCallback(() => {\n' +
|
|
56
56
|
' async function fetchData() {\n' +
|
|
57
57
|
' // You can await here\n' +
|
|
58
58
|
' const response = await MyAPI.getData(someId);\n' +
|
|
@@ -11,10 +11,12 @@ export default function useKeyedChildListeners() {
|
|
|
11
11
|
string,
|
|
12
12
|
KeyedListenerMap[K] | undefined
|
|
13
13
|
>;
|
|
14
|
-
}>(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
}>(
|
|
15
|
+
Object.assign(Object.create(null), {
|
|
16
|
+
getState: {},
|
|
17
|
+
beforeRemove: {},
|
|
18
|
+
})
|
|
19
|
+
);
|
|
18
20
|
|
|
19
21
|
const addKeyedListener = React.useCallback(
|
|
20
22
|
<T extends keyof KeyedListenerMap>(
|