This commit is contained in:
satyajit.happy
2019-06-10 05:33:47 +02:00
parent 2b7f72f0b7
commit 33fd99c842
5 changed files with 129 additions and 13 deletions

View File

@@ -6,6 +6,7 @@ import {
useNavigationBuilder,
NavigationState,
NavigationProp,
CommonAction,
} from '../src/index';
type Props = {
@@ -30,11 +31,12 @@ const StackRouter = {
}: {
routeNames: string[];
initialRouteName?: string;
}) {
}): NavigationState {
const index = routeNames.indexOf(initialRouteName);
return {
index,
names: routeNames,
routes: routeNames.slice(0, index + 1).map(name => ({
name,
key: `${name}-${shortid()}`,
@@ -42,7 +44,10 @@ const StackRouter = {
};
},
reduce(state: NavigationState, action: Action) {
reduce(
state: NavigationState,
action: Action | CommonAction
): NavigationState | null {
switch (action.type) {
case 'PUSH':
return {
@@ -56,6 +61,7 @@ const StackRouter = {
},
],
};
case 'POP':
return state.index > 0
? {
@@ -64,6 +70,38 @@ const StackRouter = {
routes: state.routes.slice(0, state.routes.length - 1),
}
: state;
case 'NAVIGATE':
if (state.names.includes(action.payload.name)) {
// If the route already exists, navigate to that
const index = state.routes.findIndex(
route => route.name === action.payload.name
);
if (index === -1) {
return StackRouter.reduce(state, {
type: 'PUSH',
payload: { name: action.payload.name },
});
}
return {
...state,
index,
routes: state.routes.slice(0, index + 1),
};
}
return null;
case 'GO_BACK':
return state.index > 0
? StackRouter.reduce(state, { type: 'POP' })
: state;
case 'RESET':
return action.payload;
default:
return state;
}

View File

@@ -6,6 +6,7 @@ import {
useNavigationBuilder,
NavigationState,
NavigationProp,
CommonAction,
} from '../src/index';
type Props = {
@@ -28,11 +29,12 @@ const TabRouter = {
}: {
routeNames: string[];
initialRouteName?: string;
}) {
}): NavigationState {
const index = routeNames.indexOf(initialRouteName);
return {
index,
names: routeNames,
routes: routeNames.map(name => ({
name,
key: `${name}-${shortid()}`,
@@ -40,15 +42,49 @@ const TabRouter = {
};
},
reduce(state: NavigationState, action: Action) {
reduce(
state: NavigationState,
action: Action | CommonAction
): NavigationState | null {
switch (action.type) {
case 'JUMP_TO':
case 'JUMP_TO': {
const index = state.routes.findIndex(
route => route.name === action.payload.name
);
if (index === -1) {
throw new Error(
`Couldn't find route "${action.payload.name}" in the state.`
);
}
return {
...state,
index: state.routes.findIndex(
route => route.name === action.payload.name
),
index,
};
}
case 'NAVIGATE': {
const index = state.routes.findIndex(
route => route.name === action.payload.name
);
if (index === -1) {
return null;
}
return TabRouter.reduce(state, {
type: 'JUMP_TO',
payload: { name: action.payload.name },
});
}
case 'RESET':
return action.payload;
case 'GO_BACK':
return null;
default:
return state;
}

24
src/BaseActions.tsx Normal file
View File

@@ -0,0 +1,24 @@
import { NavigationState } from './types';
export type Action =
| { type: 'GO_BACK' }
| {
type: 'NAVIGATE';
payload: { name: string };
}
| {
type: 'RESET';
payload: NavigationState;
};
export function goBack(): Action {
return { type: 'GO_BACK' };
}
export function navigate(name: string): Action {
return { type: 'NAVIGATE', payload: { name } };
}
export function reset(state: NavigationState): Action {
return { type: 'RESET', payload: state };
}

View File

@@ -1,5 +1,10 @@
import * as BaseActions from './BaseActions';
export type CommonAction = BaseActions.Action;
export type NavigationState = {
index: number;
names: string[];
routes: Array<Route & { state?: NavigationState }>;
};
@@ -18,7 +23,10 @@ export type Router<Action extends NavigationAction = NavigationAction> = {
routeNames: string[];
initialRouteName?: string;
}): NavigationState;
reduce(state: NavigationState, action: Action): NavigationState;
reduce(
state: NavigationState,
action: Action | CommonAction
): NavigationState | null;
actions: { [key: string]: (...args: any) => Action };
};
@@ -27,8 +35,15 @@ export type NavigationHelpers<
> = {
dispatch: (action: NavigationAction) => void;
} & {
[key in keyof T['actions']]: (...args: Parameters<T['actions'][key]>) => void;
};
[key in keyof typeof BaseActions]: (
...args: Parameters<typeof BaseActions[key]>
) => void;
} &
{
[key in keyof T['actions']]: (
...args: Parameters<T['actions'][key]>
) => void;
};
export type NavigationProp<
T extends { actions: Router['actions'] } = { actions: {} }

View File

@@ -8,6 +8,7 @@ import {
} from './types';
import Screen, { Props as ScreenProps } from './Screen';
import SceneView from './SceneView';
import * as BaseActions from './actions';
type Options = {
initialRouteName?: string;
@@ -65,11 +66,13 @@ export default function useNavigationBuilder(router: Router, options: Options) {
return result;
});
const actions = { ...router.actions, ...BaseActions };
return {
...parentNavigationHelpers,
...Object.keys(router.actions).reduce(
...Object.keys(actions).reduce(
(acc, name) => {
acc[name] = (...args: any) => dispatch(router.actions[name](...args));
acc[name] = (...args: any) => dispatch(actions[name](...args));
return acc;
},
{} as { [key: string]: () => void }