mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-05-19 02:51:06 +08:00
wip
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
24
src/BaseActions.tsx
Normal 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 };
|
||||
}
|
||||
@@ -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: {} }
|
||||
|
||||
@@ -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 }
|
||||
|
||||
Reference in New Issue
Block a user