mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-06 17:34:59 +08:00
feat: handle navigating with both with both key and name (#83)
This commit is contained in:
committed by
Satyajit Sahoo
parent
c951027ebb
commit
6b75cbaaa6
@@ -10,7 +10,8 @@ export type Action =
|
||||
type: 'NAVIGATE';
|
||||
payload:
|
||||
| { name: string; key?: undefined; params?: object }
|
||||
| { key: string; name?: undefined; params?: object };
|
||||
| { key: string; name?: undefined; params?: object }
|
||||
| { key: string; name: string; params?: object };
|
||||
source?: string;
|
||||
target?: string;
|
||||
}
|
||||
@@ -38,7 +39,10 @@ export function goBack(): Action {
|
||||
}
|
||||
|
||||
export function navigate(
|
||||
route: { key: string; params?: object } | { name: string; params?: object }
|
||||
route:
|
||||
| { key: string; params?: object }
|
||||
| { name: string; params?: object }
|
||||
| { name: string; key: string; params?: object }
|
||||
): Action;
|
||||
export function navigate(name: string, params?: object): Action;
|
||||
export function navigate(...args: any): Action {
|
||||
@@ -47,12 +51,9 @@ export function navigate(...args: any): Action {
|
||||
} else {
|
||||
const payload = args[0];
|
||||
|
||||
if (
|
||||
(payload.hasOwnProperty('key') && payload.hasOwnProperty('name')) ||
|
||||
(!payload.hasOwnProperty('key') && !payload.hasOwnProperty('name'))
|
||||
) {
|
||||
if (!payload.hasOwnProperty('key') && !payload.hasOwnProperty('name')) {
|
||||
throw new Error(
|
||||
'While calling navigate with an object as the argument, you need to specify either name or key'
|
||||
'While calling navigate with an object as the argument, you need to specify name or key'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,42 +7,7 @@ import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
|
||||
|
||||
beforeEach(() => (MockRouterKey.current = 0));
|
||||
|
||||
it('throws if NAVIGATE dispatched with both key and name', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||
|
||||
return descriptors[state.routes[state.index].key].render();
|
||||
};
|
||||
|
||||
const FooScreen = (props: any) => {
|
||||
React.useEffect(() => {
|
||||
props.navigation.navigate({ key: '1', name: '2' });
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator initialRouteName="foo">
|
||||
<Screen
|
||||
name="foo"
|
||||
component={FooScreen}
|
||||
initialParams={{ count: 10 }}
|
||||
/>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
'While calling navigate with an object as the argument, you need to specify either name or key'
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if NAVIGATE dispatched neither both key nor name', () => {
|
||||
it('throws if NAVIGATE dispatched neither key nor name', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||
|
||||
@@ -73,6 +38,6 @@ it('throws if NAVIGATE dispatched neither both key nor name', () => {
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
'While calling navigate with an object as the argument, you need to specify either name or key'
|
||||
'While calling navigate with an object as the argument, you need to specify name or key'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -287,7 +287,7 @@ type NavigationHelpersCommon<
|
||||
navigate<RouteName extends keyof ParamList>(
|
||||
route:
|
||||
| { key: string; params?: ParamList[RouteName] }
|
||||
| { name: RouteName; params: ParamList[RouteName] }
|
||||
| { name: RouteName; key?: string; params: ParamList[RouteName] }
|
||||
): void;
|
||||
|
||||
/**
|
||||
|
||||
@@ -267,6 +267,51 @@ it('handles navigate action', () => {
|
||||
CommonActions.navigate({ key: 'unknown' })
|
||||
)
|
||||
).toBe(null);
|
||||
|
||||
expect(
|
||||
router.getStateForAction(
|
||||
{
|
||||
stale: false,
|
||||
key: 'root',
|
||||
index: 1,
|
||||
routeNames: ['baz', 'bar', 'qux'],
|
||||
routes: [{ key: 'baz-0', name: 'baz' }, { key: 'bar', name: 'bar' }],
|
||||
},
|
||||
{
|
||||
type: 'NAVIGATE',
|
||||
payload: { key: 'baz-0', name: 'baz' },
|
||||
}
|
||||
)
|
||||
).toEqual({
|
||||
stale: false,
|
||||
key: 'root',
|
||||
index: 0,
|
||||
routeNames: ['baz', 'bar', 'qux'],
|
||||
routes: [{ key: 'baz-0', name: 'baz' }],
|
||||
});
|
||||
|
||||
expect(
|
||||
router.getStateForAction(
|
||||
{
|
||||
stale: false,
|
||||
key: 'root',
|
||||
index: 1,
|
||||
routeNames: ['baz', 'bar', 'qux'],
|
||||
routes: [{ key: 'baz-0', name: 'baz' }, { key: 'bar', name: 'bar' }],
|
||||
},
|
||||
CommonActions.navigate({ key: 'baz-1', name: 'baz' })
|
||||
)
|
||||
).toEqual({
|
||||
stale: false,
|
||||
key: 'root',
|
||||
index: 2,
|
||||
routeNames: ['baz', 'bar', 'qux'],
|
||||
routes: [
|
||||
{ key: 'baz-0', name: 'baz' },
|
||||
{ key: 'bar', name: 'bar' },
|
||||
{ key: 'baz-1', name: 'baz' },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('handles go back action', () => {
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
export type StackActionType =
|
||||
| {
|
||||
type: 'PUSH';
|
||||
payload: { name: string; params?: object };
|
||||
payload: { name: string; key?: string | undefined; params?: object };
|
||||
source?: string;
|
||||
target?: string;
|
||||
}
|
||||
@@ -151,7 +151,10 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
routes: [
|
||||
...state.routes,
|
||||
{
|
||||
key: `${action.payload.name}-${shortid()}`,
|
||||
key:
|
||||
action.payload.key === undefined
|
||||
? `${action.payload.name}-${shortid()}`
|
||||
: action.payload.key,
|
||||
name: action.payload.name,
|
||||
params: action.payload.params,
|
||||
},
|
||||
@@ -199,14 +202,16 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
let index = -1;
|
||||
|
||||
if (
|
||||
state.routes[state.index].name === action.payload.name ||
|
||||
(state.routes[state.index].name === action.payload.name &&
|
||||
action.payload.key === undefined) ||
|
||||
state.routes[state.index].key === action.payload.key
|
||||
) {
|
||||
index = state.index;
|
||||
} else {
|
||||
for (let i = state.routes.length - 1; i >= 0; i--) {
|
||||
if (
|
||||
state.routes[i].name === action.payload.name ||
|
||||
(state.routes[i].name === action.payload.name &&
|
||||
action.payload.key === undefined) ||
|
||||
state.routes[i].key === action.payload.key
|
||||
) {
|
||||
index = i;
|
||||
@@ -215,7 +220,11 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
}
|
||||
}
|
||||
|
||||
if (index === -1 && action.payload.key) {
|
||||
if (
|
||||
index === -1 &&
|
||||
action.payload.key &&
|
||||
action.payload.name === undefined
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -223,6 +232,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
return router.getStateForAction(state, {
|
||||
type: 'PUSH',
|
||||
payload: {
|
||||
key: action.payload.key,
|
||||
name: action.payload.name,
|
||||
params: action.payload.params,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user