Skip to content
This repository has been archived by the owner on Feb 8, 2020. It is now read-only.

feat: accept router to be a function #22

Merged
merged 5 commits into from
Jul 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
328 changes: 166 additions & 162 deletions example/StackNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Router,
BaseRouter,
createNavigator,
DefaultRouterOptions,
} from '../src/index';

type Props = {
Expand Down Expand Up @@ -68,192 +69,195 @@ export type StackNavigationProp<
popToTop(): void;
};

const StackRouter: Router<NavigationState, CommonAction | Action> = {
...BaseRouter,

getInitialState({
routeNames,
initialRouteName = routeNames[0],
initialParamsList,
}) {
const index = routeNames.indexOf(initialRouteName);

return {
key: `stack-${shortid()}`,
index,
routeNames,
routes: routeNames.slice(0, index + 1).map(name => ({
name,
key: `${name}-${shortid()}`,
params: initialParamsList[name],
})),
};
},

getRehydratedState({ routeNames, partialState }) {
let state = partialState;

if (state.stale) {
state = {
function StackRouter(options: DefaultRouterOptions) {
const router: Router<NavigationState, CommonAction | Action> = {
...BaseRouter,

getInitialState({ routeNames, routeParamList }) {
const index =
options.initialRouteName === undefined
? 0
: routeNames.indexOf(options.initialRouteName);

return {
key: `stack-${shortid()}`,
index,
routeNames,
routes: routeNames.slice(0, index + 1).map(name => ({
name,
key: `${name}-${shortid()}`,
params: routeParamList[name],
})),
};
},

getRehydratedState({ routeNames, partialState }) {
let state = partialState;

if (state.stale) {
state = {
...state,
stale: false,
routeNames,
key: `stack-${shortid()}`,
};
}

return state;
},

getStateForRouteNamesChange(state, { routeNames }) {
return {
...state,
stale: false,
routeNames,
key: `stack-${shortid()}`,
routes: state.routes.filter(route => routeNames.includes(route.name)),
};
}
},

getStateForRouteFocus(state, key) {
const index = state.routes.findIndex(r => r.key === key);

if (index === -1 || index === state.index) {
return state;
}

return state;
},
return {
...state,
index,
routes: state.routes.slice(0, index + 1),
};
},

getStateForRouteNamesChange(state, { routeNames }) {
return {
...state,
routeNames,
routes: state.routes.filter(route => routeNames.includes(route.name)),
};
},
getStateForAction(state, action) {
switch (action.type) {
case 'PUSH':
if (state.routeNames.includes(action.payload.name)) {
return {
...state,
index: state.index + 1,
routes: [
...state.routes,
{
key: `${action.payload.name}-${shortid()}`,
name: action.payload.name,
params: action.payload.params,
},
],
};
}

getStateForRouteFocus(state, key) {
const index = state.routes.findIndex(r => r.key === key);
return null;

case 'POP':
if (state.index > 0) {
return {
...state,
index: state.index - 1,
routes: state.routes.slice(
0,
Math.max(state.routes.length - action.payload.count, 1)
),
};
}

if (index === -1 || index === state.index) {
return state;
}
return null;

return {
...state,
index,
routes: state.routes.slice(0, index + 1),
};
},

getStateForAction(state, action) {
switch (action.type) {
case 'PUSH':
if (state.routeNames.includes(action.payload.name)) {
return {
...state,
index: state.index + 1,
routes: [
...state.routes,
{
key: `${action.payload.name}-${shortid()}`,
name: action.payload.name,
params: action.payload.params,
},
],
};
}

return null;

case 'POP':
if (state.index > 0) {
return {
...state,
index: state.index - 1,
routes: state.routes.slice(
0,
Math.max(state.routes.length - action.payload.count, 1)
),
};
}

return null;

case 'POP_TO_TOP':
return StackRouter.getStateForAction(state, {
type: 'POP',
payload: { count: state.routes.length - 1 },
});

case 'NAVIGATE':
if (
action.payload.key ||
(action.payload.name &&
state.routeNames.includes(action.payload.name))
) {
// If the route already exists, navigate to that
let index = -1;
case 'POP_TO_TOP':
return router.getStateForAction(state, {
type: 'POP',
payload: { count: state.routes.length - 1 },
});

case 'NAVIGATE':
if (
state.routes[state.index].name === action.payload.name ||
state.routes[state.index].key === action.payload.key
action.payload.key ||
(action.payload.name &&
state.routeNames.includes(action.payload.name))
) {
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].key === action.payload.key
) {
index = i;
break;
// If the route already exists, navigate to that
let index = -1;

if (
state.routes[state.index].name === action.payload.name ||
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].key === action.payload.key
) {
index = i;
break;
}
}
}
}

if (index === -1 && action.payload.key) {
return null;
}
if (index === -1 && action.payload.key) {
return null;
}

if (index === -1 && action.payload.name !== undefined) {
return router.getStateForAction(state, {
type: 'PUSH',
payload: {
name: action.payload.name,
params: action.payload.params,
},
});
}

if (index === -1 && action.payload.name !== undefined) {
return StackRouter.getStateForAction(state, {
type: 'PUSH',
payload: {
name: action.payload.name,
params: action.payload.params,
},
});
return {
...state,
index,
routes: [
...state.routes.slice(0, index),
action.payload.params !== undefined
? {
...state.routes[index],
params: {
...state.routes[index].params,
...action.payload.params,
},
}
: state.routes[index],
],
};
}
return null;

return {
...state,
index,
routes: [
...state.routes.slice(0, index),
action.payload.params !== undefined
? {
...state.routes[index],
params: {
...state.routes[index].params,
...action.payload.params,
},
}
: state.routes[index],
],
};
}
return null;

case 'GO_BACK':
return StackRouter.getStateForAction(state, {
type: 'POP',
payload: { count: 1 },
});

default:
return BaseRouter.getStateForAction(state, action);
}
},
case 'GO_BACK':
return router.getStateForAction(state, {
type: 'POP',
payload: { count: 1 },
});

actionCreators: {
push(name: string, params?: object) {
return { type: 'PUSH', payload: { name, params } };
default:
return BaseRouter.getStateForAction(state, action);
}
},
pop(count: number = 1) {
return { type: 'POP', payload: { count } };
},
popToTop() {
return { type: 'POP_TO_TOP' };

actionCreators: {
push(name: string, params?: object) {
return { type: 'PUSH', payload: { name, params } };
},
pop(count: number = 1) {
return { type: 'POP', payload: { count } };
},
popToTop() {
return { type: 'POP_TO_TOP' };
},
},
},
};
};
return router;
}

export function StackNavigator(props: Props) {
const { state, descriptors } = useNavigationBuilder<
NavigationState,
StackNavigationOptions
StackNavigationOptions,
DefaultRouterOptions
>(StackRouter, props);

return (
Expand Down
Loading