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

Commit

Permalink
feat: accept router to be a function
Browse files Browse the repository at this point in the history
  • Loading branch information
osdnk committed Jul 21, 2019
1 parent 55c0b5a commit 43e895f
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 19 deletions.
4 changes: 3 additions & 1 deletion src/__tests__/__fixtures__/MockRouter.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Router, CommonAction } from '../../types';
import { BaseRouter } from '../../index';

export type MockActions = CommonAction & { type: 'NOOP' | 'REVERSE' | 'UPDATE' };
export type MockActions = CommonAction & {
type: 'NOOP' | 'REVERSE' | 'UPDATE';
};

const MockRouter: Router<MockActions> & { key: number } = {
key: 0,
Expand Down
11 changes: 11 additions & 0 deletions src/types.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as BaseActions from './BaseActions';
import * as React from 'react';

export type CommonAction = BaseActions.Action;

Expand Down Expand Up @@ -55,6 +56,16 @@ export type ActionCreators<Action extends NavigationAction = CommonAction> = {
[key: string]: (...args: any) => Action;
};

export type DefualtOptions = {
initialRouteName?: string;
children: React.ReactNode;
};

export type RouterHelper<
Action extends NavigationAction = CommonAction,
Options extends DefualtOptions = DefualtOptions
> = Router<Action> | ((options: Options) => Router<Action>);

export type Router<Action extends NavigationAction = CommonAction> = {
/**
* Initialize the navigation state.
Expand Down
43 changes: 25 additions & 18 deletions src/useNavigationBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ import useRegisterNavigator from './useRegisterNavigator';
import useDescriptors from './useDescriptors';
import useNavigationHelpers from './useNavigationHelpers';
import useOnAction from './useOnAction';
import { Router, NavigationState, RouteConfig } from './types';
import {
Router,
NavigationState,
RouteConfig,
RouterHelper,
DefualtOptions,
} from './types';
import useOnRouteFocus from './useOnRouteFocus';
import useChildActionListeners from './useChildActionListeners';

type Options = {
initialRouteName?: string;
children: React.ReactNode;
};

const isArrayEqual = (a: any[], b: any[]) =>
a.length === b.length && a.every((it, index) => it === b[index]);

Expand All @@ -39,10 +40,12 @@ const getRouteConfigsFromChildren = (children: React.ReactNode) =>
);
}, []);

export default function useNavigationBuilder(
router: Router<any>,
options: Options
) {
export default function useNavigationBuilder<
Options extends DefualtOptions = DefualtOptions
>(router: RouterHelper<any>, options: Options) {
const { current: currentRouter } = React.useRef<Router<any>>(
typeof router === 'function' ? router(options) : router
);
useRegisterNavigator();

const screens = getRouteConfigsFromChildren(options.children).reduce(
Expand All @@ -67,7 +70,7 @@ export default function useNavigationBuilder(
);

const [initialState] = React.useState(() =>
router.getInitialState({
currentRouter.getInitialState({
routeNames,
initialRouteName,
initialParamsList,
Expand All @@ -82,14 +85,14 @@ export default function useNavigationBuilder(
performTransaction,
} = React.useContext(NavigationStateContext);

let state = router.getRehydratedState({
let state = currentRouter.getRehydratedState({
routeNames,
partialState: currentState,
});

if (!isArrayEqual(state.routeNames, routeNames)) {
// When the list of route names change, the router should handle it to remove invalid routes
const nextState = router.getStateForRouteNamesChange(state, {
const nextState = currentRouter.getStateForRouteNamesChange(state, {
routeNames,
initialRouteName,
initialParamsList,
Expand Down Expand Up @@ -119,12 +122,16 @@ export default function useNavigationBuilder(

const getState = React.useCallback(
(): NavigationState =>
router.getRehydratedState({
currentRouter.getRehydratedState({
routeNames,
partialState: getCurrentState() || state,
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
[getCurrentState, router.getRehydratedState, router.getInitialState]
[
getCurrentState,
currentRouter.getRehydratedState,
currentRouter.getInitialState,
]
);

const {
Expand All @@ -134,15 +141,15 @@ export default function useNavigationBuilder(
} = useChildActionListeners();

const onAction = useOnAction({
router,
router: currentRouter,
getState,
setState,
key,
listeners: actionListeners,
});

const onRouteFocus = useOnRouteFocus({
router,
router: currentRouter,
onAction,
key,
getState,
Expand All @@ -153,7 +160,7 @@ export default function useNavigationBuilder(
onAction,
getState,
setState,
actionCreators: router.actionCreators,
actionCreators: currentRouter.actionCreators,
});

const descriptors = useDescriptors({
Expand Down

0 comments on commit 43e895f

Please sign in to comment.