@react-navigation/core 7.0.0-alpha.11 → 7.0.0-alpha.13
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/StaticNavigation.js +32 -22
- package/lib/commonjs/StaticNavigation.js.map +1 -1
- package/lib/commonjs/deepFreeze.js +37 -0
- package/lib/commonjs/deepFreeze.js.map +1 -0
- package/lib/commonjs/useFocusEffect.js +2 -2
- package/lib/commonjs/useNavigationBuilder.js +3 -2
- package/lib/commonjs/useNavigationBuilder.js.map +1 -1
- package/lib/commonjs/useRouteCache.js +15 -1
- package/lib/commonjs/useRouteCache.js.map +1 -1
- package/lib/commonjs/useSyncState.js +12 -3
- package/lib/commonjs/useSyncState.js.map +1 -1
- package/lib/module/StaticNavigation.js +32 -22
- package/lib/module/StaticNavigation.js.map +1 -1
- package/lib/module/deepFreeze.js +29 -0
- package/lib/module/deepFreeze.js.map +1 -0
- package/lib/module/useFocusEffect.js +2 -2
- package/lib/module/useNavigationBuilder.js +3 -2
- package/lib/module/useNavigationBuilder.js.map +1 -1
- package/lib/module/useRouteCache.js +15 -1
- package/lib/module/useRouteCache.js.map +1 -1
- package/lib/module/useSyncState.js +12 -3
- package/lib/module/useSyncState.js.map +1 -1
- package/lib/typescript/src/StaticNavigation.d.ts +20 -4
- package/lib/typescript/src/StaticNavigation.d.ts.map +1 -1
- package/lib/typescript/src/deepFreeze.d.ts +3 -0
- package/lib/typescript/src/deepFreeze.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +1 -1
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationBuilder.d.ts +0 -21
- package/lib/typescript/src/useNavigationBuilder.d.ts.map +1 -1
- package/lib/typescript/src/useRouteCache.d.ts +1 -1
- package/lib/typescript/src/useRouteCache.d.ts.map +1 -1
- package/lib/typescript/src/useSyncState.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/StaticNavigation.tsx +95 -44
- package/src/deepFreeze.tsx +34 -0
- package/src/types.tsx +1 -1
- package/src/useFocusEffect.tsx +2 -2
- package/src/useNavigationBuilder.tsx +7 -4
- package/src/useRouteCache.tsx +17 -1
- package/src/useSyncState.tsx +16 -3
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const isPlainObject = (value: unknown): value is object => {
|
|
2
|
+
if (typeof value === 'object' && value !== null) {
|
|
3
|
+
return Object.getPrototypeOf(value) === Object.prototype;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
return false;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const deepFreeze = <T,>(object: T): Readonly<T> => {
|
|
10
|
+
// We only freeze in development to catch issues early
|
|
11
|
+
// Don't freeze in production to avoid unnecessary performance overhead
|
|
12
|
+
if (process.env.NODE_ENV === 'production') {
|
|
13
|
+
return object;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (Object.isFrozen(object)) {
|
|
17
|
+
return object;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!isPlainObject(object) && !Array.isArray(object)) {
|
|
21
|
+
return object;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Freeze properties before freezing self
|
|
25
|
+
for (const key in object) {
|
|
26
|
+
if (Object.getOwnPropertyDescriptor(object, key)?.configurable) {
|
|
27
|
+
const value = object[key];
|
|
28
|
+
|
|
29
|
+
deepFreeze(value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return Object.freeze(object);
|
|
34
|
+
};
|
package/src/types.tsx
CHANGED
package/src/useFocusEffect.tsx
CHANGED
|
@@ -71,7 +71,7 @@ export function useFocusEffect(effect: EffectCallback) {
|
|
|
71
71
|
}
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
-
// We need to run the effect on
|
|
74
|
+
// We need to run the effect on initial render/dep changes if the screen is focused
|
|
75
75
|
if (navigation.isFocused()) {
|
|
76
76
|
cleanup = callback();
|
|
77
77
|
isFocused = true;
|
|
@@ -79,7 +79,7 @@ export function useFocusEffect(effect: EffectCallback) {
|
|
|
79
79
|
|
|
80
80
|
const unsubscribeFocus = navigation.addListener('focus', () => {
|
|
81
81
|
// If callback was already called for focus, avoid calling it again
|
|
82
|
-
// The focus event may also fire on
|
|
82
|
+
// The focus event may also fire on initial render, so we guard against running the effect twice
|
|
83
83
|
if (isFocused) {
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
@@ -14,6 +14,7 @@ import * as React from 'react';
|
|
|
14
14
|
import { isValidElementType } from 'react-is';
|
|
15
15
|
import useLatestCallback from 'use-latest-callback';
|
|
16
16
|
|
|
17
|
+
import { deepFreeze } from './deepFreeze';
|
|
17
18
|
import { Group } from './Group';
|
|
18
19
|
import { isArrayEqual } from './isArrayEqual';
|
|
19
20
|
import { isRecordEqual } from './isRecordEqual';
|
|
@@ -457,7 +458,7 @@ export function useNavigationBuilder<
|
|
|
457
458
|
|
|
458
459
|
let state =
|
|
459
460
|
// If the state isn't initialized, or stale, use the state we initialized instead
|
|
460
|
-
// The state won't update until there's a change needed in the state we have
|
|
461
|
+
// The state won't update until there's a change needed in the state we have initialized locally
|
|
461
462
|
// So it'll be `undefined` or stale until the first navigation event happens
|
|
462
463
|
isStateInitialized(currentState)
|
|
463
464
|
? (currentState as State)
|
|
@@ -582,9 +583,11 @@ export function useNavigationBuilder<
|
|
|
582
583
|
const getState = useLatestCallback((): State => {
|
|
583
584
|
const currentState = shouldUpdate ? nextState : getCurrentState();
|
|
584
585
|
|
|
585
|
-
return (
|
|
586
|
-
isStateInitialized(currentState)
|
|
587
|
-
|
|
586
|
+
return deepFreeze(
|
|
587
|
+
(isStateInitialized(currentState)
|
|
588
|
+
? currentState
|
|
589
|
+
: initializedState) as State
|
|
590
|
+
);
|
|
588
591
|
});
|
|
589
592
|
|
|
590
593
|
const emitter = useEventEmitter<EventMapCore<State>>((e) => {
|
package/src/useRouteCache.tsx
CHANGED
|
@@ -7,7 +7,7 @@ import type { RouteProp } from './types';
|
|
|
7
7
|
type RouteCache = Map<string, RouteProp<ParamListBase>>;
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Utilities such as `getFocusedRouteNameFromRoute` need to access state.
|
|
11
11
|
* So we need a way to suppress the warning for those use cases.
|
|
12
12
|
* This is fine since they are internal utilities and this is not public API.
|
|
13
13
|
*/
|
|
@@ -41,6 +41,22 @@ export function useRouteCache<State extends NavigationState>(
|
|
|
41
41
|
proxy = routeWithoutState;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
45
|
+
// FIXME: since the state is updated with mutation, the route object cannot be frozen
|
|
46
|
+
// As a workaround, loop through the object and make the properties readonly
|
|
47
|
+
for (const key in proxy) {
|
|
48
|
+
// @ts-expect-error: this is fine since we are looping through the object
|
|
49
|
+
const value = proxy[key];
|
|
50
|
+
|
|
51
|
+
Object.defineProperty(proxy, key, {
|
|
52
|
+
enumerable: true,
|
|
53
|
+
configurable: true,
|
|
54
|
+
writable: false,
|
|
55
|
+
value,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
44
60
|
Object.defineProperty(proxy, CHILD_STATE, {
|
|
45
61
|
enumerable: false,
|
|
46
62
|
configurable: true,
|
package/src/useSyncState.tsx
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
+
import { deepFreeze } from './deepFreeze';
|
|
4
|
+
|
|
3
5
|
const createStore = <T,>(getInitialState: () => T) => {
|
|
4
6
|
const listeners: (() => void)[] = [];
|
|
5
7
|
|
|
6
|
-
let
|
|
8
|
+
let initialized = false;
|
|
9
|
+
let state: T;
|
|
10
|
+
|
|
11
|
+
const getState = () => {
|
|
12
|
+
if (initialized) {
|
|
13
|
+
return state;
|
|
14
|
+
}
|
|
7
15
|
|
|
8
|
-
|
|
16
|
+
initialized = true;
|
|
17
|
+
state = deepFreeze(getInitialState());
|
|
18
|
+
|
|
19
|
+
return state;
|
|
20
|
+
};
|
|
9
21
|
|
|
10
22
|
const setState = (newState: T) => {
|
|
11
|
-
state = newState;
|
|
23
|
+
state = deepFreeze(newState);
|
|
24
|
+
|
|
12
25
|
listeners.forEach((listener) => listener());
|
|
13
26
|
};
|
|
14
27
|
|