@react-navigation/core 7.0.2 → 7.0.4
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/commonjs/BaseNavigationContainer.js +10 -2
- package/lib/commonjs/BaseNavigationContainer.js.map +1 -1
- package/lib/commonjs/NavigationBuilderContext.js +7 -1
- package/lib/commonjs/NavigationBuilderContext.js.map +1 -1
- package/lib/commonjs/SceneView.js +29 -4
- package/lib/commonjs/SceneView.js.map +1 -1
- package/lib/commonjs/StaticNavigation.js +1 -1
- package/lib/commonjs/StaticNavigation.js.map +1 -1
- package/lib/commonjs/useDescriptors.js +5 -1
- package/lib/commonjs/useDescriptors.js.map +1 -1
- package/lib/commonjs/useNavigationBuilder.js +3 -2
- package/lib/commonjs/useNavigationBuilder.js.map +1 -1
- package/lib/commonjs/useScheduleUpdate.js +29 -0
- package/lib/commonjs/useScheduleUpdate.js.map +1 -0
- package/lib/commonjs/useSyncState.js +41 -2
- package/lib/commonjs/useSyncState.js.map +1 -1
- package/lib/module/BaseNavigationContainer.js +10 -2
- package/lib/module/BaseNavigationContainer.js.map +1 -1
- package/lib/module/NavigationBuilderContext.js +7 -1
- package/lib/module/NavigationBuilderContext.js.map +1 -1
- package/lib/module/SceneView.js +29 -4
- package/lib/module/SceneView.js.map +1 -1
- package/lib/module/StaticNavigation.js +1 -1
- package/lib/module/StaticNavigation.js.map +1 -1
- package/lib/module/useDescriptors.js +5 -1
- package/lib/module/useDescriptors.js.map +1 -1
- package/lib/module/useNavigationBuilder.js +3 -2
- package/lib/module/useNavigationBuilder.js.map +1 -1
- package/lib/module/useScheduleUpdate.js +23 -0
- package/lib/module/useScheduleUpdate.js.map +1 -0
- package/lib/module/useSyncState.js +40 -2
- package/lib/module/useSyncState.js.map +1 -1
- package/lib/typescript/commonjs/src/BaseNavigationContainer.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/NavigationBuilderContext.d.ts +2 -0
- package/lib/typescript/commonjs/src/NavigationBuilderContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/SceneView.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/useDescriptors.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/useNavigationBuilder.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/useScheduleUpdate.d.ts +9 -0
- package/lib/typescript/commonjs/src/useScheduleUpdate.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/useSyncState.d.ts +7 -1
- package/lib/typescript/commonjs/src/useSyncState.d.ts.map +1 -1
- package/lib/typescript/commonjs/tsconfig.build.tsbuildinfo +1 -1
- package/lib/typescript/module/src/BaseNavigationContainer.d.ts.map +1 -1
- package/lib/typescript/module/src/NavigationBuilderContext.d.ts +2 -0
- package/lib/typescript/module/src/NavigationBuilderContext.d.ts.map +1 -1
- package/lib/typescript/module/src/SceneView.d.ts.map +1 -1
- package/lib/typescript/module/src/useDescriptors.d.ts.map +1 -1
- package/lib/typescript/module/src/useNavigationBuilder.d.ts.map +1 -1
- package/lib/typescript/module/src/useScheduleUpdate.d.ts +9 -0
- package/lib/typescript/module/src/useScheduleUpdate.d.ts.map +1 -0
- package/lib/typescript/module/src/useSyncState.d.ts +7 -1
- package/lib/typescript/module/src/useSyncState.d.ts.map +1 -1
- package/lib/typescript/module/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/src/BaseNavigationContainer.tsx +14 -4
- package/src/NavigationBuilderContext.tsx +8 -0
- package/src/SceneView.tsx +31 -3
- package/src/useDescriptors.tsx +11 -3
- package/src/useNavigationBuilder.tsx +2 -1
- package/src/useScheduleUpdate.tsx +21 -0
- package/src/useSyncState.tsx +48 -2
|
@@ -103,9 +103,10 @@ export const BaseNavigationContainer = React.forwardRef(
|
|
|
103
103
|
);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
const { state, getState, setState, scheduleUpdate, flushUpdates } =
|
|
107
|
+
useSyncState<State>(() =>
|
|
108
|
+
getPartialState(initialState == null ? undefined : initialState)
|
|
109
|
+
);
|
|
109
110
|
|
|
110
111
|
const isFirstMountRef = React.useRef<boolean>(true);
|
|
111
112
|
|
|
@@ -260,9 +261,18 @@ export const BaseNavigationContainer = React.forwardRef(
|
|
|
260
261
|
addKeyedListener,
|
|
261
262
|
onDispatchAction,
|
|
262
263
|
onOptionsChange,
|
|
264
|
+
scheduleUpdate,
|
|
265
|
+
flushUpdates,
|
|
263
266
|
stackRef,
|
|
264
267
|
}),
|
|
265
|
-
[
|
|
268
|
+
[
|
|
269
|
+
addListener,
|
|
270
|
+
addKeyedListener,
|
|
271
|
+
onDispatchAction,
|
|
272
|
+
onOptionsChange,
|
|
273
|
+
scheduleUpdate,
|
|
274
|
+
flushUpdates,
|
|
275
|
+
]
|
|
266
276
|
);
|
|
267
277
|
|
|
268
278
|
const isInitialRef = React.useRef(true);
|
|
@@ -61,8 +61,16 @@ export const NavigationBuilderContext = React.createContext<{
|
|
|
61
61
|
onRouteFocus?: (key: string) => void;
|
|
62
62
|
onDispatchAction: (action: NavigationAction, noop: boolean) => void;
|
|
63
63
|
onOptionsChange: (options: object) => void;
|
|
64
|
+
scheduleUpdate: (callback: () => void) => void;
|
|
65
|
+
flushUpdates: () => void;
|
|
64
66
|
stackRef?: React.MutableRefObject<string | undefined>;
|
|
65
67
|
}>({
|
|
66
68
|
onDispatchAction: () => undefined,
|
|
67
69
|
onOptionsChange: () => undefined,
|
|
70
|
+
scheduleUpdate: () => {
|
|
71
|
+
throw new Error("Couldn't find a context for scheduling updates.");
|
|
72
|
+
},
|
|
73
|
+
flushUpdates: () => {
|
|
74
|
+
throw new Error("Couldn't find a context for flushing updates.");
|
|
75
|
+
},
|
|
68
76
|
});
|
package/src/SceneView.tsx
CHANGED
|
@@ -72,9 +72,37 @@ export function SceneView<
|
|
|
72
72
|
|
|
73
73
|
setState({
|
|
74
74
|
...state,
|
|
75
|
-
routes: state.routes.map((r) =>
|
|
76
|
-
r.key
|
|
77
|
-
|
|
75
|
+
routes: state.routes.map((r) => {
|
|
76
|
+
if (r.key !== route.key) {
|
|
77
|
+
return r;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const nextRoute = { ...r, state: child };
|
|
81
|
+
|
|
82
|
+
// Before updating the state, cleanup any nested screen and state
|
|
83
|
+
// This will avoid the navigator trying to handle them again
|
|
84
|
+
if (
|
|
85
|
+
nextRoute.params &&
|
|
86
|
+
(('state' in nextRoute.params &&
|
|
87
|
+
typeof nextRoute.params.state === 'object' &&
|
|
88
|
+
nextRoute.params.state !== null) ||
|
|
89
|
+
('screen' in nextRoute.params &&
|
|
90
|
+
typeof nextRoute.params.screen === 'string'))
|
|
91
|
+
) {
|
|
92
|
+
// @ts-expect-error: we don't have correct type for params
|
|
93
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
94
|
+
const { state, screen, params, initial, ...rest } =
|
|
95
|
+
nextRoute.params;
|
|
96
|
+
|
|
97
|
+
if (Object.keys(rest).length) {
|
|
98
|
+
nextRoute.params = rest;
|
|
99
|
+
} else {
|
|
100
|
+
delete nextRoute.params;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return nextRoute;
|
|
105
|
+
}),
|
|
78
106
|
});
|
|
79
107
|
},
|
|
80
108
|
[getState, route.key, setState]
|
package/src/useDescriptors.tsx
CHANGED
|
@@ -116,9 +116,13 @@ export function useDescriptors<
|
|
|
116
116
|
const [options, setOptions] = React.useState<Record<string, ScreenOptions>>(
|
|
117
117
|
{}
|
|
118
118
|
);
|
|
119
|
-
const {
|
|
120
|
-
|
|
121
|
-
|
|
119
|
+
const {
|
|
120
|
+
onDispatchAction,
|
|
121
|
+
onOptionsChange,
|
|
122
|
+
scheduleUpdate,
|
|
123
|
+
flushUpdates,
|
|
124
|
+
stackRef,
|
|
125
|
+
} = React.useContext(NavigationBuilderContext);
|
|
122
126
|
|
|
123
127
|
const context = React.useMemo(
|
|
124
128
|
() => ({
|
|
@@ -129,6 +133,8 @@ export function useDescriptors<
|
|
|
129
133
|
onRouteFocus,
|
|
130
134
|
onDispatchAction,
|
|
131
135
|
onOptionsChange,
|
|
136
|
+
scheduleUpdate,
|
|
137
|
+
flushUpdates,
|
|
132
138
|
stackRef,
|
|
133
139
|
}),
|
|
134
140
|
[
|
|
@@ -139,6 +145,8 @@ export function useDescriptors<
|
|
|
139
145
|
onRouteFocus,
|
|
140
146
|
onDispatchAction,
|
|
141
147
|
onOptionsChange,
|
|
148
|
+
scheduleUpdate,
|
|
149
|
+
flushUpdates,
|
|
142
150
|
stackRef,
|
|
143
151
|
]
|
|
144
152
|
);
|
|
@@ -46,6 +46,7 @@ import { useOnAction } from './useOnAction';
|
|
|
46
46
|
import { useOnGetState } from './useOnGetState';
|
|
47
47
|
import { useOnRouteFocus } from './useOnRouteFocus';
|
|
48
48
|
import { useRegisterNavigator } from './useRegisterNavigator';
|
|
49
|
+
import { useScheduleUpdate } from './useScheduleUpdate';
|
|
49
50
|
|
|
50
51
|
// This is to make TypeScript compiler happy
|
|
51
52
|
PrivateValueStore;
|
|
@@ -561,7 +562,7 @@ export function useNavigationBuilder<
|
|
|
561
562
|
|
|
562
563
|
const shouldUpdate = state !== nextState;
|
|
563
564
|
|
|
564
|
-
|
|
565
|
+
useScheduleUpdate(() => {
|
|
565
566
|
if (shouldUpdate) {
|
|
566
567
|
// If the state needs to be updated, we'll schedule an update
|
|
567
568
|
setState(nextState);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import { NavigationBuilderContext } from './NavigationBuilderContext';
|
|
4
|
+
/**
|
|
5
|
+
* When screen config changes, we want to update the navigator in the same update phase.
|
|
6
|
+
* However, navigation state is in the root component and React won't let us update it from a child.
|
|
7
|
+
* This is a workaround for that, the scheduled update is stored in the ref without actually calling setState.
|
|
8
|
+
* It lets all subsequent updates access the latest state so it stays correct.
|
|
9
|
+
* Then we call setState during after the component updates.
|
|
10
|
+
*/
|
|
11
|
+
export function useScheduleUpdate(callback: () => void) {
|
|
12
|
+
const { scheduleUpdate, flushUpdates } = React.useContext(
|
|
13
|
+
NavigationBuilderContext
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
// FIXME: This is potentially unsafe
|
|
17
|
+
// However, since we are using sync store, it might be fine
|
|
18
|
+
scheduleUpdate(callback);
|
|
19
|
+
|
|
20
|
+
React.useEffect(flushUpdates);
|
|
21
|
+
}
|
package/src/useSyncState.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import useLatestCallback from 'use-latest-callback';
|
|
2
3
|
|
|
3
4
|
import { deepFreeze } from './deepFreeze';
|
|
4
5
|
|
|
@@ -19,10 +20,16 @@ const createStore = <T,>(getInitialState: () => T) => {
|
|
|
19
20
|
return state;
|
|
20
21
|
};
|
|
21
22
|
|
|
23
|
+
let isBatching = false;
|
|
24
|
+
let didUpdate = false;
|
|
25
|
+
|
|
22
26
|
const setState = (newState: T) => {
|
|
23
27
|
state = deepFreeze(newState);
|
|
28
|
+
didUpdate = true;
|
|
24
29
|
|
|
25
|
-
|
|
30
|
+
if (!isBatching) {
|
|
31
|
+
listeners.forEach((listener) => listener());
|
|
32
|
+
}
|
|
26
33
|
};
|
|
27
34
|
|
|
28
35
|
const subscribe = (callback: () => void) => {
|
|
@@ -37,9 +44,21 @@ const createStore = <T,>(getInitialState: () => T) => {
|
|
|
37
44
|
};
|
|
38
45
|
};
|
|
39
46
|
|
|
47
|
+
const batchUpdates = (callback: () => void) => {
|
|
48
|
+
isBatching = true;
|
|
49
|
+
callback();
|
|
50
|
+
isBatching = false;
|
|
51
|
+
|
|
52
|
+
if (didUpdate) {
|
|
53
|
+
didUpdate = false;
|
|
54
|
+
listeners.forEach((listener) => listener());
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
40
58
|
return {
|
|
41
59
|
getState,
|
|
42
60
|
setState,
|
|
61
|
+
batchUpdates,
|
|
43
62
|
subscribe,
|
|
44
63
|
};
|
|
45
64
|
};
|
|
@@ -55,5 +74,32 @@ export function useSyncState<T>(getInitialState: () => T) {
|
|
|
55
74
|
|
|
56
75
|
React.useDebugValue(state);
|
|
57
76
|
|
|
58
|
-
|
|
77
|
+
const pendingUpdatesRef = React.useRef<(() => void)[]>([]);
|
|
78
|
+
|
|
79
|
+
const scheduleUpdate = useLatestCallback((callback: () => void) => {
|
|
80
|
+
pendingUpdatesRef.current.push(callback);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const flushUpdates = useLatestCallback(() => {
|
|
84
|
+
const pendingUpdates = pendingUpdatesRef.current;
|
|
85
|
+
|
|
86
|
+
pendingUpdatesRef.current = [];
|
|
87
|
+
|
|
88
|
+
if (pendingUpdates.length !== 0) {
|
|
89
|
+
store.batchUpdates(() => {
|
|
90
|
+
// Flush all the pending updates
|
|
91
|
+
for (const update of pendingUpdates) {
|
|
92
|
+
update();
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
state,
|
|
100
|
+
getState: store.getState,
|
|
101
|
+
setState: store.setState,
|
|
102
|
+
scheduleUpdate,
|
|
103
|
+
flushUpdates,
|
|
104
|
+
} as const;
|
|
59
105
|
}
|