mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-13 22:42:25 +08:00
Compare commits
10 Commits
@react-nav
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
264537bdb4 | ||
|
|
ca4a36070a | ||
|
|
4ca5cc6329 | ||
|
|
25c3fc440f | ||
|
|
89fa363883 | ||
|
|
bec2f754d4 | ||
|
|
b277927925 | ||
|
|
72993c6463 | ||
|
|
3fbfb70699 | ||
|
|
abdf9d12b5 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1 +0,0 @@
|
||||
* text eol=lf
|
||||
1
.github/workflows/expo-preview.yml
vendored
1
.github/workflows/expo-preview.yml
vendored
@@ -5,6 +5,7 @@ jobs:
|
||||
publish:
|
||||
name: Install and publish
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.head.repo.owner.login == 'react-navigation'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
InitialState,
|
||||
useLinking,
|
||||
NavigationContainerRef,
|
||||
NavigationNativeContainer,
|
||||
NavigationContainer,
|
||||
DefaultTheme,
|
||||
DarkTheme,
|
||||
} from '@react-navigation/native';
|
||||
@@ -202,7 +202,7 @@ export default function App() {
|
||||
{Platform.OS === 'ios' && (
|
||||
<StatusBar barStyle={theme.dark ? 'light-content' : 'dark-content'} />
|
||||
)}
|
||||
<NavigationNativeContainer
|
||||
<NavigationContainer
|
||||
ref={containerRef}
|
||||
initialState={initialState}
|
||||
onStateChange={state =>
|
||||
@@ -307,7 +307,7 @@ export default function App() {
|
||||
)}
|
||||
</Drawer.Screen>
|
||||
</Drawer.Navigator>
|
||||
</NavigationNativeContainer>
|
||||
</NavigationContainer>
|
||||
</PaperProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.45](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.44...@react-navigation/bottom-tabs@5.0.0-alpha.45) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.44](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.43...@react-navigation/bottom-tabs@5.0.0-alpha.44) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.43](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.42...@react-navigation/bottom-tabs@5.0.0-alpha.43) (2020-02-03)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"android",
|
||||
"tab"
|
||||
],
|
||||
"version": "5.0.0-alpha.43",
|
||||
"version": "5.0.0-alpha.45",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -30,7 +30,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.31",
|
||||
"@react-navigation/routers": "^5.0.0-alpha.33",
|
||||
"color": "^3.1.2",
|
||||
"react-native-iphone-x-helper": "^1.2.1"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.34](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.33...@react-navigation/compat@5.0.0-alpha.34) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/compat
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.33](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.32...@react-navigation/compat@5.0.0-alpha.33) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/compat
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.32](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.31...@react-navigation/compat@5.0.0-alpha.32) (2020-02-03)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/compat
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/compat",
|
||||
"description": "Compatibility layer to write navigator definitions in static configuration format",
|
||||
"version": "5.0.0-alpha.32",
|
||||
"version": "5.0.0-alpha.34",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/compat",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -21,7 +21,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.31"
|
||||
"@react-navigation/routers": "^5.0.0-alpha.33"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^16.9.17",
|
||||
|
||||
@@ -3,6 +3,30 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.43](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.42...@react-navigation/core@5.0.0-alpha.43) (2020-02-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* improve error message for unhandled action ([ca4a360](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/ca4a36070a21c4fe86cb1cc55a4452dca293f215))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add initialRouteName property to config ([#322](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/322)) ([4ca5cc6](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/4ca5cc632992187f12870281e4cf4c7d1f799967))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.42](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.41...@react-navigation/core@5.0.0-alpha.42) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.41](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.40...@react-navigation/core@5.0.0-alpha.41) (2020-02-03)
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"react-native",
|
||||
"react-navigation"
|
||||
],
|
||||
"version": "5.0.0-alpha.41",
|
||||
"version": "5.0.0-alpha.43",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/core",
|
||||
"main": "lib/commonjs/index.js",
|
||||
|
||||
300
packages/core/src/BaseNavigationContainer.tsx
Normal file
300
packages/core/src/BaseNavigationContainer.tsx
Normal file
@@ -0,0 +1,300 @@
|
||||
import * as React from 'react';
|
||||
import * as CommonActions from './CommonActions';
|
||||
import EnsureSingleNavigator from './EnsureSingleNavigator';
|
||||
import NavigationBuilderContext from './NavigationBuilderContext';
|
||||
import useFocusedListeners from './useFocusedListeners';
|
||||
import useDevTools from './useDevTools';
|
||||
import useStateGetters from './useStateGetters';
|
||||
import isSerializable from './isSerializable';
|
||||
|
||||
import {
|
||||
Route,
|
||||
NavigationState,
|
||||
InitialState,
|
||||
PartialState,
|
||||
NavigationAction,
|
||||
NavigationContainerRef,
|
||||
NavigationContainerProps,
|
||||
} from './types';
|
||||
import useEventEmitter from './useEventEmitter';
|
||||
|
||||
type State = NavigationState | PartialState<NavigationState> | undefined;
|
||||
|
||||
const MISSING_CONTEXT_ERROR =
|
||||
"We couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'?";
|
||||
|
||||
export const NavigationStateContext = React.createContext<{
|
||||
isDefault?: true;
|
||||
state?: NavigationState | PartialState<NavigationState>;
|
||||
getState: () => NavigationState | PartialState<NavigationState> | undefined;
|
||||
setState: (
|
||||
state: NavigationState | PartialState<NavigationState> | undefined
|
||||
) => void;
|
||||
key?: string;
|
||||
performTransaction: (action: () => void) => void;
|
||||
}>({
|
||||
isDefault: true,
|
||||
|
||||
get getState(): any {
|
||||
throw new Error(MISSING_CONTEXT_ERROR);
|
||||
},
|
||||
get setState(): any {
|
||||
throw new Error(MISSING_CONTEXT_ERROR);
|
||||
},
|
||||
get performTransaction(): any {
|
||||
throw new Error(MISSING_CONTEXT_ERROR);
|
||||
},
|
||||
});
|
||||
|
||||
let hasWarnedForSerialization = false;
|
||||
|
||||
/**
|
||||
* Remove `key` and `routeNames` from the state objects recursively to get partial state.
|
||||
*
|
||||
* @param state Initial state object.
|
||||
*/
|
||||
const getPartialState = (
|
||||
state: InitialState | undefined
|
||||
): PartialState<NavigationState> | undefined => {
|
||||
if (state === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { key, routeNames, ...partialState } = state;
|
||||
|
||||
// @ts-ignore
|
||||
return {
|
||||
...partialState,
|
||||
stale: true,
|
||||
routes: state.routes.map(route => {
|
||||
if (route.state === undefined) {
|
||||
return route as Route<string> & {
|
||||
state?: PartialState<NavigationState>;
|
||||
};
|
||||
}
|
||||
|
||||
return { ...route, state: getPartialState(route.state) };
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Container component which holds the navigation state.
|
||||
* This should be rendered at the root wrapping the whole app.
|
||||
*
|
||||
* @param props.initialState Initial state object for the navigation tree.
|
||||
* @param props.onStateChange Callback which is called with the latest navigation state when it changes.
|
||||
* @param props.children Child elements to render the content.
|
||||
* @param props.ref Ref object which refers to the navigation object containing helper methods.
|
||||
*/
|
||||
const BaseNavigationContainer = React.forwardRef(
|
||||
function BaseNavigationContainer(
|
||||
{
|
||||
initialState,
|
||||
onStateChange,
|
||||
independent,
|
||||
children,
|
||||
}: NavigationContainerProps,
|
||||
ref: React.Ref<NavigationContainerRef>
|
||||
) {
|
||||
const parent = React.useContext(NavigationStateContext);
|
||||
|
||||
if (!parent.isDefault && !independent) {
|
||||
throw new Error(
|
||||
"Looks like you have nested a 'NavigationContainer' inside another. Normally you need only one container at the root of the app, so this was probably an error. If this was intentional, pass 'independent={true}' explicitely."
|
||||
);
|
||||
}
|
||||
|
||||
const [state, setNavigationState] = React.useState<State>(() =>
|
||||
getPartialState(initialState == null ? undefined : initialState)
|
||||
);
|
||||
|
||||
const navigationStateRef = React.useRef<State>();
|
||||
const transactionStateRef = React.useRef<State | null>(null);
|
||||
const isTransactionActiveRef = React.useRef<boolean>(false);
|
||||
const isFirstMountRef = React.useRef<boolean>(true);
|
||||
const skipTrackingRef = React.useRef<boolean>(false);
|
||||
|
||||
const performTransaction = React.useCallback((callback: () => void) => {
|
||||
if (isTransactionActiveRef.current) {
|
||||
throw new Error(
|
||||
"Only one transaction can be active at a time. Did you accidentally nest 'performTransaction'?"
|
||||
);
|
||||
}
|
||||
|
||||
setNavigationState((navigationState: State) => {
|
||||
isTransactionActiveRef.current = true;
|
||||
transactionStateRef.current = navigationState;
|
||||
|
||||
try {
|
||||
callback();
|
||||
} finally {
|
||||
isTransactionActiveRef.current = false;
|
||||
}
|
||||
|
||||
return transactionStateRef.current;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const getState = React.useCallback(
|
||||
() =>
|
||||
transactionStateRef.current !== null
|
||||
? transactionStateRef.current
|
||||
: navigationStateRef.current,
|
||||
[]
|
||||
);
|
||||
|
||||
const setState = React.useCallback((navigationState: State) => {
|
||||
if (transactionStateRef.current === null) {
|
||||
throw new Error(
|
||||
"Any 'setState' calls need to be done inside 'performTransaction'"
|
||||
);
|
||||
}
|
||||
|
||||
transactionStateRef.current = navigationState;
|
||||
}, []);
|
||||
|
||||
const reset = React.useCallback(
|
||||
(state: NavigationState) => {
|
||||
performTransaction(() => {
|
||||
skipTrackingRef.current = true;
|
||||
setState(state);
|
||||
});
|
||||
},
|
||||
[performTransaction, setState]
|
||||
);
|
||||
|
||||
const { trackState, trackAction } = useDevTools({
|
||||
name: '@react-navigation',
|
||||
reset,
|
||||
state,
|
||||
});
|
||||
|
||||
const {
|
||||
listeners,
|
||||
addListener: addFocusedListener,
|
||||
} = useFocusedListeners();
|
||||
|
||||
const { getStateForRoute, addStateGetter } = useStateGetters();
|
||||
|
||||
const dispatch = (
|
||||
action: NavigationAction | ((state: NavigationState) => NavigationAction)
|
||||
) => {
|
||||
listeners[0](navigation => navigation.dispatch(action));
|
||||
};
|
||||
|
||||
const canGoBack = () => {
|
||||
const { result, handled } = listeners[0](navigation =>
|
||||
navigation.canGoBack()
|
||||
);
|
||||
|
||||
if (handled) {
|
||||
return result;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const resetRoot = React.useCallback(
|
||||
(state?: PartialState<NavigationState> | NavigationState) => {
|
||||
performTransaction(() => {
|
||||
trackAction('@@RESET_ROOT');
|
||||
setState(state);
|
||||
});
|
||||
},
|
||||
[performTransaction, setState, trackAction]
|
||||
);
|
||||
|
||||
const getRootState = React.useCallback(() => {
|
||||
return getStateForRoute('root');
|
||||
}, [getStateForRoute]);
|
||||
|
||||
const emitter = useEventEmitter();
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
...(Object.keys(CommonActions) as (keyof typeof CommonActions)[]).reduce<
|
||||
any
|
||||
>((acc, name) => {
|
||||
acc[name] = (...args: any[]) =>
|
||||
dispatch(
|
||||
CommonActions[name](
|
||||
// @ts-ignore
|
||||
...args
|
||||
)
|
||||
);
|
||||
return acc;
|
||||
}, {}),
|
||||
...emitter.create('root'),
|
||||
resetRoot,
|
||||
dispatch,
|
||||
canGoBack,
|
||||
getRootState,
|
||||
}));
|
||||
|
||||
const builderContext = React.useMemo(
|
||||
() => ({
|
||||
addFocusedListener,
|
||||
addStateGetter,
|
||||
trackAction,
|
||||
}),
|
||||
[addFocusedListener, trackAction, addStateGetter]
|
||||
);
|
||||
|
||||
const context = React.useMemo(
|
||||
() => ({
|
||||
state,
|
||||
performTransaction,
|
||||
getState,
|
||||
setState,
|
||||
}),
|
||||
[getState, performTransaction, setState, state]
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (
|
||||
state !== undefined &&
|
||||
!isSerializable(state) &&
|
||||
!hasWarnedForSerialization
|
||||
) {
|
||||
hasWarnedForSerialization = true;
|
||||
|
||||
console.warn(
|
||||
"We found non-serializable values in the navigation state, which can break usage such as persisting and restoring state. This might happen if you passed non-serializable values such as function, class instances etc. in params. If you need to use functions in your options, you can use 'navigation.setOptions' instead."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
emitter.emit({
|
||||
type: 'state',
|
||||
data: { state },
|
||||
});
|
||||
|
||||
if (skipTrackingRef.current) {
|
||||
skipTrackingRef.current = false;
|
||||
} else {
|
||||
trackState(getRootState);
|
||||
}
|
||||
|
||||
navigationStateRef.current = state;
|
||||
transactionStateRef.current = null;
|
||||
|
||||
if (!isFirstMountRef.current && onStateChange) {
|
||||
onStateChange(getRootState());
|
||||
}
|
||||
|
||||
isFirstMountRef.current = false;
|
||||
}, [state, onStateChange, trackState, getRootState, emitter]);
|
||||
|
||||
return (
|
||||
<NavigationBuilderContext.Provider value={builderContext}>
|
||||
<NavigationStateContext.Provider value={context}>
|
||||
<EnsureSingleNavigator>{children}</EnsureSingleNavigator>
|
||||
</NavigationStateContext.Provider>
|
||||
</NavigationBuilderContext.Provider>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default BaseNavigationContainer;
|
||||
@@ -1,295 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import * as CommonActions from './CommonActions';
|
||||
import EnsureSingleNavigator from './EnsureSingleNavigator';
|
||||
import NavigationBuilderContext from './NavigationBuilderContext';
|
||||
import useFocusedListeners from './useFocusedListeners';
|
||||
import useDevTools from './useDevTools';
|
||||
import useStateGetters from './useStateGetters';
|
||||
import isSerializable from './isSerializable';
|
||||
|
||||
import {
|
||||
Route,
|
||||
NavigationState,
|
||||
InitialState,
|
||||
PartialState,
|
||||
NavigationAction,
|
||||
NavigationContainerRef,
|
||||
NavigationContainerProps,
|
||||
} from './types';
|
||||
import useEventEmitter from './useEventEmitter';
|
||||
|
||||
type State = NavigationState | PartialState<NavigationState> | undefined;
|
||||
|
||||
const MISSING_CONTEXT_ERROR =
|
||||
"We couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'?";
|
||||
|
||||
export const NavigationStateContext = React.createContext<{
|
||||
isDefault?: true;
|
||||
state?: NavigationState | PartialState<NavigationState>;
|
||||
getState: () => NavigationState | PartialState<NavigationState> | undefined;
|
||||
setState: (
|
||||
state: NavigationState | PartialState<NavigationState> | undefined
|
||||
) => void;
|
||||
key?: string;
|
||||
performTransaction: (action: () => void) => void;
|
||||
}>({
|
||||
isDefault: true,
|
||||
|
||||
get getState(): any {
|
||||
throw new Error(MISSING_CONTEXT_ERROR);
|
||||
},
|
||||
get setState(): any {
|
||||
throw new Error(MISSING_CONTEXT_ERROR);
|
||||
},
|
||||
get performTransaction(): any {
|
||||
throw new Error(MISSING_CONTEXT_ERROR);
|
||||
},
|
||||
});
|
||||
|
||||
let hasWarnedForSerialization = false;
|
||||
|
||||
/**
|
||||
* Remove `key` and `routeNames` from the state objects recursively to get partial state.
|
||||
*
|
||||
* @param state Initial state object.
|
||||
*/
|
||||
const getPartialState = (
|
||||
state: InitialState | undefined
|
||||
): PartialState<NavigationState> | undefined => {
|
||||
if (state === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { key, routeNames, ...partialState } = state;
|
||||
|
||||
// @ts-ignore
|
||||
return {
|
||||
...partialState,
|
||||
stale: true,
|
||||
routes: state.routes.map(route => {
|
||||
if (route.state === undefined) {
|
||||
return route as Route<string> & {
|
||||
state?: PartialState<NavigationState>;
|
||||
};
|
||||
}
|
||||
|
||||
return { ...route, state: getPartialState(route.state) };
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Container component which holds the navigation state.
|
||||
* This should be rendered at the root wrapping the whole app.
|
||||
*
|
||||
* @param props.initialState Initial state object for the navigation tree.
|
||||
* @param props.onStateChange Callback which is called with the latest navigation state when it changes.
|
||||
* @param props.children Child elements to render the content.
|
||||
* @param props.ref Ref object which refers to the navigation object containing helper methods.
|
||||
*/
|
||||
const Container = React.forwardRef(function NavigationContainer(
|
||||
{
|
||||
initialState,
|
||||
onStateChange,
|
||||
independent,
|
||||
children,
|
||||
}: NavigationContainerProps,
|
||||
ref: React.Ref<NavigationContainerRef>
|
||||
) {
|
||||
const parent = React.useContext(NavigationStateContext);
|
||||
|
||||
if (!parent.isDefault && !independent) {
|
||||
throw new Error(
|
||||
"Looks like you have nested a 'NavigationContainer' inside another. Normally you need only one container at the root of the app, so this was probably an error. If this was intentional, pass 'independent={true}' explicitely."
|
||||
);
|
||||
}
|
||||
|
||||
const [state, setNavigationState] = React.useState<State>(() =>
|
||||
getPartialState(initialState == null ? undefined : initialState)
|
||||
);
|
||||
|
||||
const navigationStateRef = React.useRef<State>();
|
||||
const transactionStateRef = React.useRef<State | null>(null);
|
||||
const isTransactionActiveRef = React.useRef<boolean>(false);
|
||||
const isFirstMountRef = React.useRef<boolean>(true);
|
||||
const skipTrackingRef = React.useRef<boolean>(false);
|
||||
|
||||
const performTransaction = React.useCallback((callback: () => void) => {
|
||||
if (isTransactionActiveRef.current) {
|
||||
throw new Error(
|
||||
"Only one transaction can be active at a time. Did you accidentally nest 'performTransaction'?"
|
||||
);
|
||||
}
|
||||
|
||||
setNavigationState((navigationState: State) => {
|
||||
isTransactionActiveRef.current = true;
|
||||
transactionStateRef.current = navigationState;
|
||||
|
||||
try {
|
||||
callback();
|
||||
} finally {
|
||||
isTransactionActiveRef.current = false;
|
||||
}
|
||||
|
||||
return transactionStateRef.current;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const getState = React.useCallback(
|
||||
() =>
|
||||
transactionStateRef.current !== null
|
||||
? transactionStateRef.current
|
||||
: navigationStateRef.current,
|
||||
[]
|
||||
);
|
||||
|
||||
const setState = React.useCallback((navigationState: State) => {
|
||||
if (transactionStateRef.current === null) {
|
||||
throw new Error(
|
||||
"Any 'setState' calls need to be done inside 'performTransaction'"
|
||||
);
|
||||
}
|
||||
|
||||
transactionStateRef.current = navigationState;
|
||||
}, []);
|
||||
|
||||
const reset = React.useCallback(
|
||||
(state: NavigationState) => {
|
||||
performTransaction(() => {
|
||||
skipTrackingRef.current = true;
|
||||
setState(state);
|
||||
});
|
||||
},
|
||||
[performTransaction, setState]
|
||||
);
|
||||
|
||||
const { trackState, trackAction } = useDevTools({
|
||||
name: '@react-navigation',
|
||||
reset,
|
||||
state,
|
||||
});
|
||||
|
||||
const { listeners, addListener: addFocusedListener } = useFocusedListeners();
|
||||
|
||||
const { getStateForRoute, addStateGetter } = useStateGetters();
|
||||
|
||||
const dispatch = (
|
||||
action: NavigationAction | ((state: NavigationState) => NavigationAction)
|
||||
) => {
|
||||
listeners[0](navigation => navigation.dispatch(action));
|
||||
};
|
||||
|
||||
const canGoBack = () => {
|
||||
const { result, handled } = listeners[0](navigation =>
|
||||
navigation.canGoBack()
|
||||
);
|
||||
|
||||
if (handled) {
|
||||
return result;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const resetRoot = React.useCallback(
|
||||
(state?: PartialState<NavigationState> | NavigationState) => {
|
||||
performTransaction(() => {
|
||||
trackAction('@@RESET_ROOT');
|
||||
setState(state);
|
||||
});
|
||||
},
|
||||
[performTransaction, setState, trackAction]
|
||||
);
|
||||
|
||||
const getRootState = React.useCallback(() => {
|
||||
return getStateForRoute('root');
|
||||
}, [getStateForRoute]);
|
||||
|
||||
const emitter = useEventEmitter();
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
...(Object.keys(CommonActions) as (keyof typeof CommonActions)[]).reduce<
|
||||
any
|
||||
>((acc, name) => {
|
||||
acc[name] = (...args: any[]) =>
|
||||
dispatch(
|
||||
CommonActions[name](
|
||||
// @ts-ignore
|
||||
...args
|
||||
)
|
||||
);
|
||||
return acc;
|
||||
}, {}),
|
||||
...emitter.create('root'),
|
||||
resetRoot,
|
||||
dispatch,
|
||||
canGoBack,
|
||||
getRootState,
|
||||
}));
|
||||
|
||||
const builderContext = React.useMemo(
|
||||
() => ({
|
||||
addFocusedListener,
|
||||
addStateGetter,
|
||||
trackAction,
|
||||
}),
|
||||
[addFocusedListener, trackAction, addStateGetter]
|
||||
);
|
||||
|
||||
const context = React.useMemo(
|
||||
() => ({
|
||||
state,
|
||||
performTransaction,
|
||||
getState,
|
||||
setState,
|
||||
}),
|
||||
[getState, performTransaction, setState, state]
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (
|
||||
state !== undefined &&
|
||||
!isSerializable(state) &&
|
||||
!hasWarnedForSerialization
|
||||
) {
|
||||
hasWarnedForSerialization = true;
|
||||
|
||||
console.warn(
|
||||
"We found non-serializable values in the navigation state, which can break usage such as persisting and restoring state. This might happen if you passed non-serializable values such as function, class instances etc. in params. If you need to use functions in your options, you can use 'navigation.setOptions' instead."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
emitter.emit({
|
||||
type: 'state',
|
||||
data: { state },
|
||||
});
|
||||
|
||||
if (skipTrackingRef.current) {
|
||||
skipTrackingRef.current = false;
|
||||
} else {
|
||||
trackState(getRootState);
|
||||
}
|
||||
|
||||
navigationStateRef.current = state;
|
||||
transactionStateRef.current = null;
|
||||
|
||||
if (!isFirstMountRef.current && onStateChange) {
|
||||
onStateChange(getRootState());
|
||||
}
|
||||
|
||||
isFirstMountRef.current = false;
|
||||
}, [state, onStateChange, trackState, getRootState, emitter]);
|
||||
|
||||
return (
|
||||
<NavigationBuilderContext.Provider value={builderContext}>
|
||||
<NavigationStateContext.Provider value={context}>
|
||||
<EnsureSingleNavigator>{children}</EnsureSingleNavigator>
|
||||
</NavigationStateContext.Provider>
|
||||
</NavigationBuilderContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
export default Container;
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { NavigationStateContext } from './NavigationContainer';
|
||||
import { NavigationStateContext } from './BaseNavigationContainer';
|
||||
import NavigationContext from './NavigationContext';
|
||||
import NavigationRouteContext from './NavigationRouteContext';
|
||||
import StaticContainer from './StaticContainer';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import { act, render } from 'react-native-testing-library';
|
||||
import NavigationContainer, {
|
||||
import BaseNavigationContainer, {
|
||||
NavigationStateContext,
|
||||
} from '../NavigationContainer';
|
||||
} from '../BaseNavigationContainer';
|
||||
import MockRouter, { MockActions } from './__fixtures__/MockRouter';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import Screen from '../Screen';
|
||||
@@ -85,9 +85,9 @@ it('throws when setState is called outside performTransaction', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<Test />
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
@@ -112,9 +112,9 @@ it('throws when nesting performTransaction', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<Test />
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
@@ -125,11 +125,11 @@ it('throws when nesting performTransaction', () => {
|
||||
it('throws when nesting containers', () => {
|
||||
expect(() =>
|
||||
render(
|
||||
<NavigationContainer>
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<React.Fragment />
|
||||
</NavigationContainer>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
)
|
||||
).toThrowError(
|
||||
"Looks like you have nested a 'NavigationContainer' inside another."
|
||||
@@ -137,11 +137,11 @@ it('throws when nesting containers', () => {
|
||||
|
||||
expect(() =>
|
||||
render(
|
||||
<NavigationContainer>
|
||||
<NavigationContainer independent>
|
||||
<BaseNavigationContainer>
|
||||
<BaseNavigationContainer independent>
|
||||
<React.Fragment />
|
||||
</NavigationContainer>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
)
|
||||
).not.toThrowError(
|
||||
"Looks like you have nested a 'NavigationContainer' inside another."
|
||||
@@ -223,7 +223,7 @@ it('handle dispatching with ref', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer
|
||||
<BaseNavigationContainer
|
||||
ref={ref}
|
||||
initialState={initialState}
|
||||
onStateChange={onStateChange}
|
||||
@@ -248,7 +248,7 @@ it('handle dispatching with ref', () => {
|
||||
)}
|
||||
</Screen>
|
||||
</ParentNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element).update(element);
|
||||
@@ -301,7 +301,7 @@ it('handle resetting state with ref', () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer ref={ref} onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer ref={ref} onStateChange={onStateChange}>
|
||||
<TestNavigator>
|
||||
<Screen name="foo">{() => null}</Screen>
|
||||
<Screen name="foo2">
|
||||
@@ -322,7 +322,7 @@ it('handle resetting state with ref', () => {
|
||||
)}
|
||||
</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element).update(element);
|
||||
@@ -389,7 +389,7 @@ it('handles getRootState', () => {
|
||||
const ref = React.createRef<NavigationContainerRef>();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer ref={ref}>
|
||||
<BaseNavigationContainer ref={ref}>
|
||||
<TestNavigator initialRouteName="foo">
|
||||
<Screen name="foo">
|
||||
{() => (
|
||||
@@ -401,7 +401,7 @@ it('handles getRootState', () => {
|
||||
</Screen>
|
||||
<Screen name="bar">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
@@ -450,13 +450,13 @@ it('emits state events when the state changes', () => {
|
||||
const ref = React.createRef<NavigationContainerRef>();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer ref={ref}>
|
||||
<BaseNavigationContainer ref={ref}>
|
||||
<TestNavigator>
|
||||
<Screen name="foo">{() => null}</Screen>
|
||||
<Screen name="bar">{() => null}</Screen>
|
||||
<Screen name="baz">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element).update(element);
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { render } from 'react-native-testing-library';
|
||||
import Screen from '../Screen';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
|
||||
|
||||
@@ -26,7 +26,7 @@ it('throws if NAVIGATE dispatched neither key nor name', () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator initialRouteName="foo">
|
||||
<Screen
|
||||
name="foo"
|
||||
@@ -34,7 +34,7 @@ it('throws if NAVIGATE dispatched neither key nor name', () => {
|
||||
initialParams={{ count: 10 }}
|
||||
/>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
|
||||
@@ -394,13 +394,6 @@ it('handles parse in nested object for second route depth and and path and parse
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
Bar: {
|
||||
path: 'bar/:id',
|
||||
parse: {
|
||||
id: Number,
|
||||
},
|
||||
stringify: {
|
||||
id: (id: number) => `id=${id}`,
|
||||
},
|
||||
screens: {
|
||||
Baz: 'baz',
|
||||
},
|
||||
@@ -433,24 +426,260 @@ it('handles parse in nested object for second route depth and and path and parse
|
||||
);
|
||||
});
|
||||
|
||||
it('returns undefined if path is empty', () => {
|
||||
it('handles initialRouteName', () => {
|
||||
const path = '/baz';
|
||||
const config = {
|
||||
Foo: {
|
||||
path: 'foo/:id',
|
||||
starting: true,
|
||||
stringify: {
|
||||
id: (id: number) => `id=${id}`,
|
||||
},
|
||||
initialRouteName: 'Foe',
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
Bar: {
|
||||
path: 'bar/:id',
|
||||
parse: {
|
||||
id: Number,
|
||||
screens: {
|
||||
Baz: 'baz',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const state = {
|
||||
routes: [
|
||||
{
|
||||
name: 'Foo',
|
||||
state: {
|
||||
index: 1,
|
||||
routes: [
|
||||
{
|
||||
name: 'Foe',
|
||||
},
|
||||
{
|
||||
name: 'Bar',
|
||||
state: {
|
||||
routes: [{ name: 'Baz' }],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(getStateFromPath(path, config)).toEqual(state);
|
||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||
state
|
||||
);
|
||||
});
|
||||
|
||||
it('handles initialRouteName included in path', () => {
|
||||
const path = '/baz';
|
||||
const config = {
|
||||
Foo: {
|
||||
initialRouteName: 'Foe',
|
||||
screens: {
|
||||
Foe: {
|
||||
screens: {
|
||||
Baz: 'baz',
|
||||
},
|
||||
},
|
||||
Bar: 'bar',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const state = {
|
||||
routes: [
|
||||
{
|
||||
name: 'Foo',
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Foe',
|
||||
state: {
|
||||
routes: [{ name: 'Baz' }],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(getStateFromPath(path, config)).toEqual(state);
|
||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||
state
|
||||
);
|
||||
});
|
||||
|
||||
it('handles two initialRouteNames', () => {
|
||||
const path = '/bar/sweet/apple/foe/bis/jane?count=10&answer=42&valid=true';
|
||||
const config = {
|
||||
Foo: {
|
||||
path: 'foo',
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
},
|
||||
},
|
||||
Bar: 'bar/:type/:fruit',
|
||||
Baz: {
|
||||
initialRouteName: 'Bos',
|
||||
screens: {
|
||||
Bos: 'bos',
|
||||
Bis: {
|
||||
path: 'bis/:author',
|
||||
stringify: {
|
||||
id: (id: number) => `id=${id}`,
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toLowerCase()),
|
||||
},
|
||||
parse: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const state = {
|
||||
routes: [
|
||||
{
|
||||
name: 'Bar',
|
||||
params: { fruit: 'apple', type: 'sweet' },
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Foo',
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Foe',
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Baz',
|
||||
state: {
|
||||
index: 1,
|
||||
routes: [
|
||||
{ name: 'Bos' },
|
||||
{
|
||||
name: 'Bis',
|
||||
params: {
|
||||
author: 'Jane',
|
||||
count: 10,
|
||||
answer: '42',
|
||||
valid: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(getStateFromPath(path, config)).toEqual(state);
|
||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||
state
|
||||
);
|
||||
});
|
||||
|
||||
it('accepts initialRouteName without config for it', () => {
|
||||
const path = '/bar/sweet/apple/foe/bis/jane?count=10&answer=42&valid=true';
|
||||
const config = {
|
||||
Foo: {
|
||||
path: 'foo',
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
},
|
||||
},
|
||||
Bar: 'bar/:type/:fruit',
|
||||
Baz: {
|
||||
initialRouteName: 'Bas',
|
||||
screens: {
|
||||
Bos: 'bos',
|
||||
Bis: {
|
||||
path: 'bis/:author',
|
||||
stringify: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toLowerCase()),
|
||||
},
|
||||
parse: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const state = {
|
||||
routes: [
|
||||
{
|
||||
name: 'Bar',
|
||||
params: { fruit: 'apple', type: 'sweet' },
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Foo',
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Foe',
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Baz',
|
||||
state: {
|
||||
index: 1,
|
||||
routes: [
|
||||
{ name: 'Bas' },
|
||||
{
|
||||
name: 'Bis',
|
||||
params: {
|
||||
author: 'Jane',
|
||||
count: 10,
|
||||
answer: '42',
|
||||
valid: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(getStateFromPath(path, config)).toEqual(state);
|
||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||
state
|
||||
);
|
||||
});
|
||||
|
||||
it('returns undefined if path is empty', () => {
|
||||
const config = {
|
||||
Foo: {
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
Bar: {
|
||||
screens: {
|
||||
Baz: 'baz',
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { render, act } from 'react-native-testing-library';
|
||||
import Screen from '../Screen';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import useNavigation from '../useNavigation';
|
||||
import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
|
||||
@@ -28,7 +28,7 @@ it('initializes state for a navigator on navigation', () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator initialRouteName="foo">
|
||||
<Screen
|
||||
name="foo"
|
||||
@@ -44,7 +44,7 @@ it('initializes state for a navigator on navigation', () => {
|
||||
)}
|
||||
</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element).update(element);
|
||||
@@ -75,11 +75,11 @@ it("doesn't crash when initialState is null", () => {
|
||||
|
||||
const element = (
|
||||
// @ts-ignore
|
||||
<NavigationContainer initialState={null}>
|
||||
<BaseNavigationContainer initialState={null}>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={TestScreen} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element)).not.toThrowError();
|
||||
@@ -112,7 +112,7 @@ it('rehydrates state for a navigator on navigation', () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer
|
||||
<BaseNavigationContainer
|
||||
initialState={initialState}
|
||||
onStateChange={onStateChange}
|
||||
>
|
||||
@@ -120,7 +120,7 @@ it('rehydrates state for a navigator on navigation', () => {
|
||||
<Screen name="foo" component={jest.fn()} />
|
||||
<Screen name="bar" component={BarScreen} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element).update(element);
|
||||
@@ -166,7 +166,7 @@ it("doesn't rehydrate state if the type of state didn't match router", () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer
|
||||
<BaseNavigationContainer
|
||||
initialState={initialState}
|
||||
onStateChange={onStateChange}
|
||||
>
|
||||
@@ -178,7 +178,7 @@ it("doesn't rehydrate state if the type of state didn't match router", () => {
|
||||
/>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element).update(element);
|
||||
@@ -219,7 +219,7 @@ it('initializes state for nested screens in React.Fragment', () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={TestScreen} />
|
||||
<React.Fragment>
|
||||
@@ -227,7 +227,7 @@ it('initializes state for nested screens in React.Fragment', () => {
|
||||
<Screen name="baz" component={jest.fn()} />
|
||||
</React.Fragment>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element).update(element);
|
||||
@@ -266,7 +266,7 @@ it('initializes state for nested navigator on navigation', () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator initialRouteName="baz">
|
||||
<Screen name="foo" component={jest.fn()} />
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
@@ -278,7 +278,7 @@ it('initializes state for nested navigator on navigation', () => {
|
||||
)}
|
||||
</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element).update(element);
|
||||
@@ -328,12 +328,12 @@ it("doesn't update state if nothing changed", () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
render(
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator initialRouteName="foo">
|
||||
<Screen name="foo" component={FooScreen} />
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(0);
|
||||
@@ -360,12 +360,12 @@ it("doesn't update state if action wasn't handled", () => {
|
||||
const spy = jest.spyOn(console, 'error').mockImplementation();
|
||||
|
||||
render(
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator initialRouteName="foo">
|
||||
<Screen name="foo" component={FooScreen} />
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(0);
|
||||
@@ -396,12 +396,12 @@ it('cleans up state when the navigator unmounts', () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={FooScreen} />
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
const root = render(element);
|
||||
@@ -422,7 +422,7 @@ it('cleans up state when the navigator unmounts', () => {
|
||||
});
|
||||
|
||||
root.update(
|
||||
<NavigationContainer onStateChange={onStateChange} children={null} />
|
||||
<BaseNavigationContainer onStateChange={onStateChange} children={null} />
|
||||
);
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(2);
|
||||
@@ -454,12 +454,12 @@ it('allows state updates by dispatching a function returning an action', () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator initialRouteName="foo">
|
||||
<Screen name="foo" component={FooScreen} />
|
||||
<Screen name="bar" component={BarScreen} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element).update(element);
|
||||
@@ -496,12 +496,12 @@ it('updates route params with setParams', () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
render(
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator initialRouteName="foo">
|
||||
<Screen name="foo" component={FooScreen} />
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
act(() => setParams({ username: 'alice' }));
|
||||
@@ -556,7 +556,7 @@ it('updates route params with setParams applied to parent', () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
render(
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator initialRouteName="foo">
|
||||
<Screen name="foo">
|
||||
{() => (
|
||||
@@ -567,7 +567,7 @@ it('updates route params with setParams applied to parent', () => {
|
||||
</Screen>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
act(() => setParams({ username: 'alice' }));
|
||||
@@ -634,22 +634,22 @@ it('handles change in route names', () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator initialRouteName="bar">
|
||||
<Screen name="foo" component={jest.fn()} />
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
root.update(
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={jest.fn()} />
|
||||
<Screen name="baz" component={jest.fn()} />
|
||||
<Screen name="qux" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(onStateChange).toBeCalledWith({
|
||||
@@ -677,7 +677,7 @@ it('navigates to nested child in a navigator', () => {
|
||||
const navigation = React.createRef<NavigationContainerRef>();
|
||||
|
||||
const element = render(
|
||||
<NavigationContainer ref={navigation} onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer ref={navigation} onStateChange={onStateChange}>
|
||||
<TestNavigator>
|
||||
<Screen name="foo">
|
||||
{() => (
|
||||
@@ -704,7 +704,7 @@ it('navigates to nested child in a navigator', () => {
|
||||
)}
|
||||
</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(element).toMatchInlineSnapshot(`"[foo-a, undefined]"`);
|
||||
@@ -752,11 +752,11 @@ it('gives access to internal state', () => {
|
||||
};
|
||||
|
||||
const root = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator initialRouteName="bar">
|
||||
<Screen name="bar" component={Test} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(root).update(root);
|
||||
@@ -778,9 +778,9 @@ it("throws if navigator doesn't have any screens", () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator />
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
@@ -812,14 +812,14 @@ it('throws if multiple navigators rendered under one container', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
@@ -836,12 +836,12 @@ it('throws when Screen is not the direct children', () => {
|
||||
const Bar = () => null;
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={jest.fn()} />
|
||||
<Bar />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
@@ -856,12 +856,12 @@ it('throws when a React Element is not the direct children', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={jest.fn()} />
|
||||
Hello world
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
@@ -877,7 +877,7 @@ it("doesn't throw when direct children is Screen or empty element", () => {
|
||||
};
|
||||
|
||||
render(
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={jest.fn()} />
|
||||
{null}
|
||||
@@ -885,7 +885,7 @@ it("doesn't throw when direct children is Screen or empty element", () => {
|
||||
{false}
|
||||
{true}
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -896,13 +896,13 @@ it('throws when multiple screens with same name are defined', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={jest.fn()} />
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
<Screen name="foo" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
@@ -917,20 +917,20 @@ it('switches rendered navigators', () => {
|
||||
};
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator key="a">
|
||||
<Screen name="foo" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() =>
|
||||
root.update(
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator key="b">
|
||||
<Screen name="foo" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
)
|
||||
).not.toThrowError(
|
||||
'Another navigator is already registered for this container.'
|
||||
@@ -944,11 +944,11 @@ it('throws if no name is passed to Screen', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name={undefined as any} component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
@@ -963,11 +963,11 @@ it('throws if invalid name is passed to Screen', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name={[] as any} component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
@@ -982,13 +982,13 @@ it('throws if both children and component are passed', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={jest.fn()}>
|
||||
{jest.fn()}
|
||||
</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
@@ -1003,11 +1003,11 @@ it('throws descriptive error for undefined screen component', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={undefined as any} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
@@ -1022,11 +1022,11 @@ it('throws descriptive error for invalid screen component', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={{} as any} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
@@ -1041,11 +1041,11 @@ it('throws descriptive error for invalid children', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo">{[] as any}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
@@ -1060,13 +1060,13 @@ it("doesn't throw if children is null", () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={jest.fn()}>
|
||||
{null as any}
|
||||
</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).not.toThrowError();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { render, act } from 'react-native-testing-library';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||
import Screen from '../Screen';
|
||||
import MockRouter, {
|
||||
MockActions,
|
||||
@@ -34,7 +34,7 @@ it('sets options with options prop as an object', () => {
|
||||
const TestScreen = (): any => 'Test screen';
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen
|
||||
name="foo"
|
||||
@@ -43,7 +43,7 @@ it('sets options with options prop as an object', () => {
|
||||
/>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
@@ -79,7 +79,7 @@ it('sets options with options prop as a fuction', () => {
|
||||
const TestScreen = (): any => 'Test screen';
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen
|
||||
name="foo"
|
||||
@@ -89,7 +89,7 @@ it('sets options with options prop as a fuction', () => {
|
||||
/>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
@@ -134,12 +134,12 @@ it('sets options with screenOptions prop as an object', () => {
|
||||
const TestScreenB = (): any => 'Test screen B';
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator screenOptions={{ title: 'Hello world' }}>
|
||||
<Screen name="foo" component={TestScreenA} />
|
||||
<Screen name="bar" component={TestScreenB} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
@@ -194,7 +194,7 @@ it('sets options with screenOptions prop as a fuction', () => {
|
||||
const TestScreenB = (): any => 'Test screen B';
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator
|
||||
screenOptions={({ route }: any) => ({
|
||||
title: `${route.name}: ${route.params.author || route.params.fruit}`,
|
||||
@@ -211,7 +211,7 @@ it('sets options with screenOptions prop as a fuction', () => {
|
||||
initialParams={{ fruit: 'Apple' }}
|
||||
/>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
@@ -266,14 +266,14 @@ it('sets initial options with setOptions', () => {
|
||||
};
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" options={{ color: 'blue' }}>
|
||||
{props => <TestScreen {...props} />}
|
||||
</Screen>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
@@ -331,14 +331,14 @@ it('updates options with setOptions', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" options={{ color: 'blue' }}>
|
||||
{props => <TestScreen {...props} />}
|
||||
</Screen>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
const root = render(element);
|
||||
@@ -396,7 +396,7 @@ it("returns correct value for canGoBack when it's not overridden", () => {
|
||||
};
|
||||
|
||||
const root = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen
|
||||
name="foo"
|
||||
@@ -405,7 +405,7 @@ it("returns correct value for canGoBack when it's not overridden", () => {
|
||||
/>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(root).update(root);
|
||||
@@ -452,11 +452,11 @@ it(`returns false for canGoBack when current router doesn't handle GO_BACK`, ()
|
||||
};
|
||||
|
||||
const root = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="baz" component={TestScreen} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(root).update(root);
|
||||
@@ -513,7 +513,7 @@ it('returns true for canGoBack when current router handles GO_BACK', () => {
|
||||
};
|
||||
|
||||
const root = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<ParentNavigator>
|
||||
<Screen name="baz">
|
||||
{() => (
|
||||
@@ -523,7 +523,7 @@ it('returns true for canGoBack when current router handles GO_BACK', () => {
|
||||
)}
|
||||
</Screen>
|
||||
</ParentNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(root).update(root);
|
||||
@@ -580,7 +580,7 @@ it('returns true for canGoBack when parent router handles GO_BACK', () => {
|
||||
};
|
||||
|
||||
const root = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="baz">
|
||||
{() => (
|
||||
@@ -597,7 +597,7 @@ it('returns true for canGoBack when parent router handles GO_BACK', () => {
|
||||
)}
|
||||
</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(root).update(root);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { render, act } from 'react-native-testing-library';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||
import Screen from '../Screen';
|
||||
import MockRouter from './__fixtures__/MockRouter';
|
||||
import { Router, NavigationState } from '../types';
|
||||
@@ -47,7 +47,7 @@ it('fires focus and blur events in root navigator', () => {
|
||||
const navigation = React.createRef<any>();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator ref={navigation}>
|
||||
<Screen
|
||||
name="first"
|
||||
@@ -66,7 +66,7 @@ it('fires focus and blur events in root navigator', () => {
|
||||
component={createComponent(fourthFocusCallback, fourthBlurCallback)}
|
||||
/>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
@@ -139,7 +139,7 @@ it('fires focus and blur events in nested navigator', () => {
|
||||
const child = React.createRef<any>();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator ref={parent}>
|
||||
<Screen
|
||||
name="first"
|
||||
@@ -170,7 +170,7 @@ it('fires focus and blur events in nested navigator', () => {
|
||||
)}
|
||||
</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
@@ -307,12 +307,12 @@ it('fires blur event when a route is removed with a delay', async () => {
|
||||
const navigation = React.createRef<any>();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator ref={navigation}>
|
||||
<Screen name="first" component={First} />
|
||||
<Screen name="second" component={Second} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
@@ -363,13 +363,13 @@ it('fires custom events', () => {
|
||||
const ref = React.createRef<any>();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator ref={ref}>
|
||||
<Screen name="first" component={createComponent(firstCallback)} />
|
||||
<Screen name="second" component={createComponent(secondCallback)} />
|
||||
<Screen name="third" component={createComponent(thirdCallback)} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
@@ -444,11 +444,11 @@ it('has option to prevent default', () => {
|
||||
const ref = React.createRef<any>();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator ref={ref}>
|
||||
<Screen name="first" component={Test} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { render, act } from 'react-native-testing-library';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import useFocusEffect from '../useFocusEffect';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||
import Screen from '../Screen';
|
||||
import MockRouter from './__fixtures__/MockRouter';
|
||||
|
||||
@@ -31,13 +31,13 @@ it('runs focus effect on focus change', () => {
|
||||
const navigation = React.createRef<any>();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer ref={navigation}>
|
||||
<BaseNavigationContainer ref={navigation}>
|
||||
<TestNavigator>
|
||||
<Screen name="first">{() => null}</Screen>
|
||||
<Screen name="second" component={Test} />
|
||||
<Screen name="third">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
@@ -84,12 +84,12 @@ it('runs focus effect on deps change', () => {
|
||||
};
|
||||
|
||||
const App = ({ count }: { count: number }) => (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="first">{() => <Test count={count} />}</Screen>
|
||||
<Screen name="second">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
const root = render(<App count={1} />);
|
||||
@@ -135,13 +135,13 @@ it('runs focus effect when initial state is given', () => {
|
||||
const navigation = React.createRef<any>();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer ref={navigation} initialState={initialState}>
|
||||
<BaseNavigationContainer ref={navigation} initialState={initialState}>
|
||||
<TestNavigator>
|
||||
<Screen name="first">{() => null}</Screen>
|
||||
<Screen name="second">{() => null}</Screen>
|
||||
<Screen name="third" component={Test} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
@@ -178,13 +178,13 @@ it('runs focus effect when only focused route is rendered', () => {
|
||||
const navigation = React.createRef<any>();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer ref={navigation}>
|
||||
<BaseNavigationContainer ref={navigation}>
|
||||
<TestNavigator>
|
||||
<Screen name="first" component={Test} />
|
||||
<Screen name="second">{() => null}</Screen>
|
||||
<Screen name="third">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
@@ -221,12 +221,12 @@ it('runs cleanup when component is unmounted', () => {
|
||||
const TestB = () => null;
|
||||
|
||||
const App = ({ mounted }: { mounted: boolean }) => (
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="first" component={mounted ? TestA : TestB} />
|
||||
<Screen name="second">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
const root = render(<App mounted />);
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { render, act } from 'react-native-testing-library';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import useIsFocused from '../useIsFocused';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||
import Screen from '../Screen';
|
||||
import MockRouter from './__fixtures__/MockRouter';
|
||||
|
||||
@@ -24,13 +24,13 @@ it('renders correct focus state', () => {
|
||||
const navigation = React.createRef<any>();
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer ref={navigation}>
|
||||
<BaseNavigationContainer ref={navigation}>
|
||||
<TestNavigator>
|
||||
<Screen name="first">{() => null}</Screen>
|
||||
<Screen name="second" component={Test} />
|
||||
<Screen name="third">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`"unfocused"`);
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { render } from 'react-native-testing-library';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import useNavigation from '../useNavigation';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||
import Screen from '../Screen';
|
||||
import MockRouter from './__fixtures__/MockRouter';
|
||||
|
||||
@@ -24,11 +24,11 @@ it('gets navigation prop from context', () => {
|
||||
};
|
||||
|
||||
render(
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={Test} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -50,7 +50,7 @@ it("gets navigation's parent from context", () => {
|
||||
};
|
||||
|
||||
render(
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo">
|
||||
{() => (
|
||||
@@ -60,7 +60,7 @@ it("gets navigation's parent from context", () => {
|
||||
)}
|
||||
</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -86,7 +86,7 @@ it("gets navigation's parent's parent from context", () => {
|
||||
};
|
||||
|
||||
render(
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo">
|
||||
{() => (
|
||||
@@ -102,7 +102,7 @@ it("gets navigation's parent's parent from context", () => {
|
||||
)}
|
||||
</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { render, act } from 'react-native-testing-library';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import useNavigationState from '../useNavigationState';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||
import Screen from '../Screen';
|
||||
import MockRouter from './__fixtures__/MockRouter';
|
||||
import { NavigationState } from '../types';
|
||||
@@ -27,13 +27,13 @@ it('gets the current navigation state', () => {
|
||||
const navigation = React.createRef<any>();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer ref={navigation}>
|
||||
<BaseNavigationContainer ref={navigation}>
|
||||
<TestNavigator>
|
||||
<Screen name="first" component={Test} />
|
||||
<Screen name="second">{() => null}</Screen>
|
||||
<Screen name="third">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
@@ -78,13 +78,13 @@ it('gets the current navigation state with selector', () => {
|
||||
const navigation = React.createRef<any>();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer ref={navigation}>
|
||||
<BaseNavigationContainer ref={navigation}>
|
||||
<TestNavigator>
|
||||
<Screen name="first" component={Test} />
|
||||
<Screen name="second">{() => null}</Screen>
|
||||
<Screen name="third">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
@@ -133,13 +133,13 @@ it('gets the correct value if selector changes', () => {
|
||||
const App = ({ selector }: { selector: (state: NavigationState) => any }) => {
|
||||
return (
|
||||
<SelectorContext.Provider value={selector}>
|
||||
<NavigationContainer ref={navigation}>
|
||||
<BaseNavigationContainer ref={navigation}>
|
||||
<TestNavigator>
|
||||
<Screen name="first" component={Test} />
|
||||
<Screen name="second">{() => null}</Screen>
|
||||
<Screen name="third">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
</SelectorContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { render } from 'react-native-testing-library';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||
import Screen from '../Screen';
|
||||
import MockRouter, {
|
||||
MockActions,
|
||||
@@ -58,7 +58,7 @@ it("lets parent handle the action if child didn't", () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
render(
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<ParentNavigator initialRouteName="baz">
|
||||
<Screen name="foo">{() => null}</Screen>
|
||||
<Screen name="bar">{() => null}</Screen>
|
||||
@@ -70,7 +70,7 @@ it("lets parent handle the action if child didn't", () => {
|
||||
)}
|
||||
</Screen>
|
||||
</ParentNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(1);
|
||||
@@ -171,7 +171,7 @@ it("lets children handle the action if parent didn't", () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer
|
||||
<BaseNavigationContainer
|
||||
initialState={initialState}
|
||||
onStateChange={onStateChange}
|
||||
>
|
||||
@@ -187,7 +187,7 @@ it("lets children handle the action if parent didn't", () => {
|
||||
)}
|
||||
</Screen>
|
||||
</ParentNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element).update(element);
|
||||
@@ -284,7 +284,7 @@ it("action doesn't bubble if target is specified", () => {
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||
<ParentNavigator>
|
||||
<Screen name="foo">{() => null}</Screen>
|
||||
<Screen name="bar" component={TestScreen} />
|
||||
@@ -297,7 +297,7 @@ it("action doesn't bubble if target is specified", () => {
|
||||
)}
|
||||
</Screen>
|
||||
</ParentNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element).update(element);
|
||||
@@ -349,7 +349,7 @@ it('logs error if no navigator handled the action', () => {
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer initialState={initialState}>
|
||||
<BaseNavigationContainer initialState={initialState}>
|
||||
<TestNavigator>
|
||||
<Screen name="foo">{() => null}</Screen>
|
||||
<Screen name="bar" component={TestScreen} />
|
||||
@@ -362,7 +362,7 @@ it('logs error if no navigator handled the action', () => {
|
||||
)}
|
||||
</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
const spy = jest.spyOn(console, 'error').mockImplementation();
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { render } from 'react-native-testing-library';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import useRoute from '../useRoute';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||
import Screen from '../Screen';
|
||||
import MockRouter from './__fixtures__/MockRouter';
|
||||
import { RouteProp } from '../types';
|
||||
@@ -25,10 +25,10 @@ it('gets route prop from context', () => {
|
||||
};
|
||||
|
||||
render(
|
||||
<NavigationContainer>
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={Test} initialParams={{ x: 1 }} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ type Options = {
|
||||
[routeName: string]:
|
||||
| string
|
||||
| {
|
||||
path: string;
|
||||
path?: string;
|
||||
stringify?: StringifyConfig;
|
||||
screens?: Options;
|
||||
};
|
||||
|
||||
@@ -8,9 +8,10 @@ type Options = {
|
||||
[routeName: string]:
|
||||
| string
|
||||
| {
|
||||
path: string;
|
||||
path?: string;
|
||||
parse?: ParseConfig;
|
||||
screens?: Options;
|
||||
initialRouteName?: string;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -21,6 +22,11 @@ type RouteConfig = {
|
||||
parse: ParseConfig | undefined;
|
||||
};
|
||||
|
||||
type InitialRouteConfig = {
|
||||
initialRouteName: string;
|
||||
connectedRoutes: string[];
|
||||
};
|
||||
|
||||
type ResultState = PartialState<NavigationState> & {
|
||||
state?: ResultState;
|
||||
};
|
||||
@@ -51,9 +57,12 @@ export default function getStateFromPath(
|
||||
if (path === '') {
|
||||
return undefined;
|
||||
}
|
||||
let initialRoutes: InitialRouteConfig[] = [];
|
||||
// Create a normalized configs array which will be easier to use
|
||||
const configs = ([] as RouteConfig[]).concat(
|
||||
...Object.keys(options).map(key => createNormalizedConfigs(key, options))
|
||||
...Object.keys(options).map(key =>
|
||||
createNormalizedConfigs(key, options, [], initialRoutes)
|
||||
)
|
||||
);
|
||||
|
||||
let result: PartialState<NavigationState> | undefined;
|
||||
@@ -65,8 +74,8 @@ export default function getStateFromPath(
|
||||
.replace(/\?.*/, ''); // Remove query params which we will handle later
|
||||
|
||||
while (remaining) {
|
||||
let routeNames;
|
||||
let params;
|
||||
let routeNames: string[] | undefined;
|
||||
let params: Record<string, any> | undefined;
|
||||
|
||||
// Go through all configs, and see if the next path segment matches our regex
|
||||
for (const config of configs) {
|
||||
@@ -111,46 +120,43 @@ export default function getStateFromPath(
|
||||
}
|
||||
|
||||
let state: InitialState;
|
||||
let routeName = routeNames.shift() as string;
|
||||
let initialRoute = findInitialRoute(routeName, initialRoutes);
|
||||
|
||||
if (routeNames.length === 1) {
|
||||
state = {
|
||||
routes: [
|
||||
{ name: routeNames.shift() as string, ...(params && { params }) },
|
||||
],
|
||||
};
|
||||
} else {
|
||||
state = {
|
||||
routes: [{ name: routeNames.shift() as string, state: { routes: [] } }],
|
||||
};
|
||||
state = createNestedState(
|
||||
initialRoute,
|
||||
routeName,
|
||||
routeNames.length === 0,
|
||||
params
|
||||
);
|
||||
|
||||
let helper = state.routes[0].state as InitialState;
|
||||
let routeName;
|
||||
if (routeNames.length > 0) {
|
||||
let nestedState = state;
|
||||
|
||||
while ((routeName = routeNames.shift())) {
|
||||
if (routeNames.length === 0) {
|
||||
helper.routes.push({
|
||||
name: routeName,
|
||||
...(params && { params }),
|
||||
});
|
||||
} else {
|
||||
helper.routes[0] = {
|
||||
name: routeName,
|
||||
state: {
|
||||
routes: [],
|
||||
},
|
||||
};
|
||||
helper = helper.routes[0].state as InitialState;
|
||||
while ((routeName = routeNames.shift() as string)) {
|
||||
initialRoute = findInitialRoute(routeName, initialRoutes);
|
||||
nestedState.routes[nestedState.index || 0].state = createNestedState(
|
||||
initialRoute,
|
||||
routeName,
|
||||
routeNames.length === 0,
|
||||
params
|
||||
);
|
||||
if (routeNames.length > 0) {
|
||||
nestedState = nestedState.routes[nestedState.index || 0]
|
||||
.state as InitialState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current) {
|
||||
// The state should be nested inside the deepest route we parsed before
|
||||
while (current.routes[0].state) {
|
||||
current = current.routes[0].state;
|
||||
while (current?.routes[current.index || 0].state) {
|
||||
current = current.routes[current.index || 0].state;
|
||||
}
|
||||
|
||||
current.routes[0].state = state;
|
||||
(current as PartialState<NavigationState>).routes[
|
||||
current?.index || 0
|
||||
].state = state;
|
||||
} else {
|
||||
result = state;
|
||||
}
|
||||
@@ -165,12 +171,14 @@ export default function getStateFromPath(
|
||||
const query = path.split('?')[1];
|
||||
|
||||
if (query) {
|
||||
while (current.routes[0].state) {
|
||||
while (current?.routes[current.index || 0].state) {
|
||||
// The query params apply to the deepest route
|
||||
current = current.routes[0].state;
|
||||
current = current.routes[current.index || 0].state;
|
||||
}
|
||||
|
||||
const route = current.routes[0];
|
||||
const route = (current as PartialState<NavigationState>).routes[
|
||||
current?.index || 0
|
||||
];
|
||||
|
||||
const params = queryString.parse(query);
|
||||
const parseFunction = findParseConfigForRoute(route.name, configs);
|
||||
@@ -192,7 +200,8 @@ export default function getStateFromPath(
|
||||
function createNormalizedConfigs(
|
||||
key: string,
|
||||
routeConfig: Options,
|
||||
routeNames: string[] = []
|
||||
routeNames: string[] = [],
|
||||
initials: InitialRouteConfig[]
|
||||
): RouteConfig[] {
|
||||
const configs: RouteConfig[] = [];
|
||||
|
||||
@@ -205,15 +214,25 @@ function createNormalizedConfigs(
|
||||
configs.push(createConfigItem(routeNames, value));
|
||||
} else if (typeof value === 'object') {
|
||||
// if an object is specified as the value (e.g. Foo: { ... }),
|
||||
// it has `path` property and
|
||||
// it can have `path` property and
|
||||
// it could have `screens` prop which has nested configs
|
||||
configs.push(createConfigItem(routeNames, value.path, value.parse));
|
||||
if (value.path) {
|
||||
configs.push(createConfigItem(routeNames, value.path, value.parse));
|
||||
}
|
||||
if (value.screens) {
|
||||
// property `initialRouteName` without `screens` has no purpose
|
||||
if (value.initialRouteName) {
|
||||
initials.push({
|
||||
initialRouteName: value.initialRouteName,
|
||||
connectedRoutes: Object.keys(value.screens),
|
||||
});
|
||||
}
|
||||
Object.keys(value.screens).forEach(nestedConfig => {
|
||||
const result = createNormalizedConfigs(
|
||||
nestedConfig,
|
||||
value.screens as Options,
|
||||
routeNames
|
||||
routeNames,
|
||||
initials
|
||||
);
|
||||
configs.push(...result);
|
||||
});
|
||||
@@ -254,3 +273,55 @@ function findParseConfigForRoute(
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// tries to find an initial route connected with the one passed
|
||||
function findInitialRoute(
|
||||
routeName: string,
|
||||
initialRoutes: InitialRouteConfig[]
|
||||
): string | undefined {
|
||||
for (const config of initialRoutes) {
|
||||
if (config.connectedRoutes.includes(routeName)) {
|
||||
return config.initialRouteName === routeName
|
||||
? undefined
|
||||
: config.initialRouteName;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// returns nested state object with values depending on whether
|
||||
// it is the end of state and if there is initialRoute for this level
|
||||
function createNestedState(
|
||||
initialRoute: string | undefined,
|
||||
routeName: string,
|
||||
isEmpty: boolean,
|
||||
params?: Record<string, any> | undefined
|
||||
): InitialState {
|
||||
if (isEmpty) {
|
||||
if (initialRoute) {
|
||||
return {
|
||||
index: 1,
|
||||
routes: [
|
||||
{ name: initialRoute },
|
||||
{ name: routeName as string, ...(params && { params }) },
|
||||
],
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
routes: [{ name: routeName as string, ...(params && { params }) }],
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (initialRoute) {
|
||||
return {
|
||||
index: 1,
|
||||
routes: [
|
||||
{ name: initialRoute },
|
||||
{ name: routeName as string, state: { routes: [] } },
|
||||
],
|
||||
};
|
||||
} else {
|
||||
return { routes: [{ name: routeName as string, state: { routes: [] } }] };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as CommonActions from './CommonActions';
|
||||
export { CommonActions };
|
||||
|
||||
export { default as BaseRouter } from './BaseRouter';
|
||||
export { default as NavigationContainer } from './NavigationContainer';
|
||||
export { default as BaseNavigationContainer } from './BaseNavigationContainer';
|
||||
export { default as createNavigatorFactory } from './createNavigatorFactory';
|
||||
|
||||
export { default as NavigationContext } from './NavigationContext';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { isValidElementType } from 'react-is';
|
||||
import { NavigationStateContext } from './NavigationContainer';
|
||||
import { NavigationStateContext } from './BaseNavigationContainer';
|
||||
import NavigationRouteContext from './NavigationRouteContext';
|
||||
import Screen from './Screen';
|
||||
import { navigate } from './CommonActions';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import * as CommonActions from './CommonActions';
|
||||
import NavigationContext from './NavigationContext';
|
||||
import { NavigationStateContext } from './NavigationContainer';
|
||||
import { NavigationStateContext } from './BaseNavigationContainer';
|
||||
import { NavigationEventEmitter } from './useEventEmitter';
|
||||
import {
|
||||
NavigationHelpers,
|
||||
@@ -51,7 +51,7 @@ export default function useNavigationHelpers<
|
||||
console.error(
|
||||
`The action '${payload.type}' with payload '${JSON.stringify(
|
||||
payload.payload
|
||||
)}' was not handled by any navigator.`
|
||||
)}' was not handled by any navigator. If you are trying to navigate to a screen, check if the screen exists in your navigator.`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.47](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/compare/@react-navigation/drawer@5.0.0-alpha.46...@react-navigation/drawer@5.0.0-alpha.47) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.46](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/compare/@react-navigation/drawer@5.0.0-alpha.45...@react-navigation/drawer@5.0.0-alpha.46) (2020-02-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* disable pan gesture by default in the browser for Apple devices ([b277927](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/b2779279251b1f157ba825cc34e39046b44f00d8)), closes [#287](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/issues/287)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.45](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/compare/@react-navigation/drawer@5.0.0-alpha.44...@react-navigation/drawer@5.0.0-alpha.45) (2020-02-03)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"material",
|
||||
"drawer"
|
||||
],
|
||||
"version": "5.0.0-alpha.45",
|
||||
"version": "5.0.0-alpha.47",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -31,7 +31,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.31",
|
||||
"@react-navigation/routers": "^5.0.0-alpha.33",
|
||||
"color": "^3.1.2",
|
||||
"react-native-iphone-x-helper": "^1.2.1"
|
||||
},
|
||||
|
||||
@@ -94,11 +94,30 @@ type Props = {
|
||||
gestureHandlerProps?: React.ComponentProps<typeof PanGestureHandler>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Disables the pan gesture by default on Apple devices in the browser.
|
||||
* https://stackoverflow.com/a/9039885
|
||||
*/
|
||||
function shouldEnableGesture(): boolean {
|
||||
if (
|
||||
Platform.OS === 'web' &&
|
||||
typeof navigator !== 'undefined' &&
|
||||
typeof window !== 'undefined'
|
||||
) {
|
||||
const isWebAppleDevice =
|
||||
/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
||||
|
||||
return !isWebAppleDevice;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export default class DrawerView extends React.PureComponent<Props> {
|
||||
static defaultProps = {
|
||||
drawerPostion: I18nManager.isRTL ? 'left' : 'right',
|
||||
drawerType: 'front',
|
||||
gestureEnabled: true,
|
||||
gestureEnabled: shouldEnableGesture(),
|
||||
swipeEdgeWidth: 32,
|
||||
swipeVelocityThreshold: 500,
|
||||
keyboardDismissMode: 'on-drag',
|
||||
|
||||
@@ -205,7 +205,7 @@ export default function DrawerView({
|
||||
<DrawerGestureContext.Provider value={drawerGestureRef}>
|
||||
<Drawer
|
||||
open={isDrawerOpen}
|
||||
gestureEnabled={gestureEnabled !== false}
|
||||
gestureEnabled={gestureEnabled}
|
||||
onOpen={handleDrawerOpen}
|
||||
onClose={handleDrawerClose}
|
||||
onGestureRef={ref => {
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.42](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.41...@react-navigation/material-bottom-tabs@5.0.0-alpha.42) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.41](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.40...@react-navigation/material-bottom-tabs@5.0.0-alpha.41) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.40](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.39...@react-navigation/material-bottom-tabs@5.0.0-alpha.40) (2020-02-03)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"material",
|
||||
"tab"
|
||||
],
|
||||
"version": "5.0.0-alpha.40",
|
||||
"version": "5.0.0-alpha.42",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -31,7 +31,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.31"
|
||||
"@react-navigation/routers": "^5.0.0-alpha.33"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.8.0",
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.41](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.0.0-alpha.40...@react-navigation/material-top-tabs@5.0.0-alpha.41) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.40](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.0.0-alpha.39...@react-navigation/material-top-tabs@5.0.0-alpha.40) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.39](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.0.0-alpha.38...@react-navigation/material-top-tabs@5.0.0-alpha.39) (2020-02-03)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"material",
|
||||
"tab"
|
||||
],
|
||||
"version": "5.0.0-alpha.39",
|
||||
"version": "5.0.0-alpha.41",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -31,7 +31,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.31",
|
||||
"@react-navigation/routers": "^5.0.0-alpha.33",
|
||||
"color": "^3.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.35](https://github.com/react-navigation/navigation-ex/tree/master/packages/native-stack/compare/@react-navigation/native-stack@5.0.0-alpha.34...@react-navigation/native-stack@5.0.0-alpha.35) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/native-stack
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.34](https://github.com/react-navigation/navigation-ex/tree/master/packages/native-stack/compare/@react-navigation/native-stack@5.0.0-alpha.33...@react-navigation/native-stack@5.0.0-alpha.34) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/native-stack
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.33](https://github.com/react-navigation/navigation-ex/tree/master/packages/native-stack/compare/@react-navigation/native-stack@5.0.0-alpha.32...@react-navigation/native-stack@5.0.0-alpha.33) (2020-02-03)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/native-stack
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"react-native",
|
||||
"react-navigation"
|
||||
],
|
||||
"version": "5.0.0-alpha.33",
|
||||
"version": "5.0.0-alpha.35",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/native-stack",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -26,7 +26,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.31"
|
||||
"@react-navigation/routers": "^5.0.0-alpha.33"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.8.0",
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.35](https://github.com/react-navigation/navigation-ex/tree/master/packages/native/compare/@react-navigation/native@5.0.0-alpha.34...@react-navigation/native@5.0.0-alpha.35) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/native
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.34](https://github.com/react-navigation/navigation-ex/tree/master/packages/native/compare/@react-navigation/native@5.0.0-alpha.33...@react-navigation/native@5.0.0-alpha.34) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/native
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.33](https://github.com/react-navigation/navigation-ex/tree/master/packages/native/compare/@react-navigation/native@5.0.0-alpha.32...@react-navigation/native@5.0.0-alpha.33) (2020-02-03)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/native
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"ios",
|
||||
"android"
|
||||
],
|
||||
"version": "5.0.0-alpha.33",
|
||||
"version": "5.0.0-alpha.35",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/native",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -27,7 +27,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/core": "^5.0.0-alpha.41"
|
||||
"@react-navigation/core": "^5.0.0-alpha.43"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.8.0",
|
||||
|
||||
44
packages/native/src/NavigationContainer.tsx
Normal file
44
packages/native/src/NavigationContainer.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
BaseNavigationContainer,
|
||||
NavigationContainerProps,
|
||||
NavigationContainerRef,
|
||||
} from '@react-navigation/core';
|
||||
import ThemeProvider from './theming/ThemeProvider';
|
||||
import DefaultTheme from './theming/DefaultTheme';
|
||||
import useBackButton from './useBackButton';
|
||||
import { Theme } from './types';
|
||||
|
||||
type Props = NavigationContainerProps & {
|
||||
theme?: Theme;
|
||||
};
|
||||
|
||||
/**
|
||||
* Container component which holds the navigation state
|
||||
* designed for mobile apps.
|
||||
* This should be rendered at the root wrapping the whole app.
|
||||
*
|
||||
* @param props.initialState Initial state object for the navigation tree.
|
||||
* @param props.onStateChange Callback which is called with the latest navigation state when it changes.
|
||||
* @param props.theme Theme object for the navigators.
|
||||
* @param props.children Child elements to render the content.
|
||||
* @param props.ref Ref object which refers to the navigation object containing helper methods.
|
||||
*/
|
||||
const NavigationContainer = React.forwardRef(function NavigationContainer(
|
||||
{ theme = DefaultTheme, ...rest }: Props,
|
||||
ref: React.Ref<NavigationContainerRef>
|
||||
) {
|
||||
const refContainer = React.useRef<NavigationContainerRef>(null);
|
||||
|
||||
useBackButton(refContainer);
|
||||
|
||||
React.useImperativeHandle(ref, () => refContainer.current);
|
||||
|
||||
return (
|
||||
<ThemeProvider value={theme}>
|
||||
<BaseNavigationContainer {...rest} ref={refContainer} />
|
||||
</ThemeProvider>
|
||||
);
|
||||
});
|
||||
|
||||
export default NavigationContainer;
|
||||
@@ -1,44 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
NavigationContainer,
|
||||
NavigationContainerProps,
|
||||
NavigationContainerRef,
|
||||
} from '@react-navigation/core';
|
||||
import ThemeProvider from './theming/ThemeProvider';
|
||||
import DefaultTheme from './theming/DefaultTheme';
|
||||
import useBackButton from './useBackButton';
|
||||
import { Theme } from './types';
|
||||
|
||||
type Props = NavigationContainerProps & {
|
||||
theme?: Theme;
|
||||
};
|
||||
|
||||
/**
|
||||
* Container component which holds the navigation state
|
||||
* designed for mobile apps.
|
||||
* This should be rendered at the root wrapping the whole app.
|
||||
*
|
||||
* @param props.initialState Initial state object for the navigation tree.
|
||||
* @param props.onStateChange Callback which is called with the latest navigation state when it changes.
|
||||
* @param props.theme Theme object for the navigators.
|
||||
* @param props.children Child elements to render the content.
|
||||
* @param props.ref Ref object which refers to the navigation object containing helper methods.
|
||||
*/
|
||||
const NavigationNativeContainer = React.forwardRef(function NativeContainer(
|
||||
{ theme = DefaultTheme, ...rest }: Props,
|
||||
ref: React.Ref<NavigationContainerRef>
|
||||
) {
|
||||
const refContainer = React.useRef<NavigationContainerRef>(null);
|
||||
|
||||
useBackButton(refContainer);
|
||||
|
||||
React.useImperativeHandle(ref, () => refContainer.current);
|
||||
|
||||
return (
|
||||
<ThemeProvider value={theme}>
|
||||
<NavigationContainer {...rest} ref={refContainer} />
|
||||
</ThemeProvider>
|
||||
export default function() {
|
||||
throw new Error(
|
||||
"'NavigationNativeContainer' has been renamed to 'NavigationContainer"
|
||||
);
|
||||
});
|
||||
|
||||
export default NavigationNativeContainer;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from '@react-navigation/core';
|
||||
|
||||
export { default as NavigationContainer } from './NavigationContainer';
|
||||
export { default as NavigationNativeContainer } from './NavigationNativeContainer';
|
||||
|
||||
export { default as useBackButton } from './useBackButton';
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.33](https://github.com/react-navigation/navigation-ex/tree/master/packages/routers/compare/@react-navigation/routers@5.0.0-alpha.32...@react-navigation/routers@5.0.0-alpha.33) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/routers
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.32](https://github.com/react-navigation/navigation-ex/tree/master/packages/routers/compare/@react-navigation/routers@5.0.0-alpha.31...@react-navigation/routers@5.0.0-alpha.32) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/routers
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.31](https://github.com/react-navigation/navigation-ex/tree/master/packages/routers/compare/@react-navigation/routers@5.0.0-alpha.30...@react-navigation/routers@5.0.0-alpha.31) (2020-02-03)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/routers
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"react-native",
|
||||
"react-navigation"
|
||||
],
|
||||
"version": "5.0.0-alpha.31",
|
||||
"version": "5.0.0-alpha.33",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/routers",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -26,7 +26,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/core": "^5.0.0-alpha.41",
|
||||
"@react-navigation/core": "^5.0.0-alpha.43",
|
||||
"shortid": "^2.2.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -3,6 +3,33 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.70](https://github.com/react-navigation/navigation-ex/tree/master/packages/stack/compare/@react-navigation/stack@5.0.0-alpha.69...@react-navigation/stack@5.0.0-alpha.70) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/stack
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.69](https://github.com/react-navigation/navigation-ex/tree/master/packages/stack/compare/@react-navigation/stack@5.0.0-alpha.68...@react-navigation/stack@5.0.0-alpha.69) (2020-02-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/stack
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.68](https://github.com/react-navigation/navigation-ex/tree/master/packages/stack/compare/@react-navigation/stack@5.0.0-alpha.67...@react-navigation/stack@5.0.0-alpha.68) (2020-02-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* use .native for masked view instead of .web ([abdf9d1](https://github.com/react-navigation/navigation-ex/tree/master/packages/stack/commit/abdf9d12b5c3fbde6414b50e3b6e082b67899772))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.67](https://github.com/react-navigation/navigation-ex/tree/master/packages/stack/compare/@react-navigation/stack@5.0.0-alpha.66...@react-navigation/stack@5.0.0-alpha.67) (2020-02-03)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/stack
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"android",
|
||||
"stack"
|
||||
],
|
||||
"version": "5.0.0-alpha.67",
|
||||
"version": "5.0.0-alpha.70",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/stack",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -30,7 +30,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.31",
|
||||
"@react-navigation/routers": "^5.0.0-alpha.33",
|
||||
"color": "^3.1.2",
|
||||
"react-native-iphone-x-helper": "^1.2.1"
|
||||
},
|
||||
|
||||
19
packages/stack/src/views/MaskedView.native.tsx
Normal file
19
packages/stack/src/views/MaskedView.native.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import * as React from 'react';
|
||||
import { UIManager } from 'react-native';
|
||||
import RNCMaskedView from '@react-native-community/masked-view';
|
||||
|
||||
type Props = React.ComponentProps<typeof RNCMaskedView> & {
|
||||
children: React.ReactElement;
|
||||
};
|
||||
|
||||
const isMaskedViewAvailable =
|
||||
// @ts-ignore
|
||||
UIManager.getViewManagerConfig('RNCMaskedView') != null;
|
||||
|
||||
export default function MaskedView({ children, ...rest }: Props) {
|
||||
if (isMaskedViewAvailable) {
|
||||
return <RNCMaskedView {...rest}>{children}</RNCMaskedView>;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
@@ -1,19 +1,10 @@
|
||||
import * as React from 'react';
|
||||
import { UIManager } from 'react-native';
|
||||
import RNCMaskedView from '@react-native-community/masked-view';
|
||||
|
||||
type Props = React.ComponentProps<typeof RNCMaskedView> & {
|
||||
type Props = {
|
||||
maskElement: React.ReactElement;
|
||||
children: React.ReactElement;
|
||||
};
|
||||
|
||||
const isMaskedViewAvailable =
|
||||
// @ts-ignore
|
||||
UIManager.getViewManagerConfig('RNCMaskedView') != null;
|
||||
|
||||
export default function MaskedView({ children, ...rest }: Props) {
|
||||
if (isMaskedViewAvailable) {
|
||||
return <RNCMaskedView {...rest}>{children}</RNCMaskedView>;
|
||||
}
|
||||
|
||||
export default function MaskedView({ children }: Props) {
|
||||
return children;
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import * as React from 'react';
|
||||
|
||||
type Props = {
|
||||
children: React.ReactElement;
|
||||
};
|
||||
|
||||
export default function MaskedView({ children }: Props) {
|
||||
return children;
|
||||
}
|
||||
Reference in New Issue
Block a user