mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-02-10 22:47:02 +08:00
As the naming suggests, this checks if route is the first one in parent. So probably doesn't make sense to check history.
126 lines
3.8 KiB
JavaScript
126 lines
3.8 KiB
JavaScript
import getChildEventSubscriber from './getChildEventSubscriber';
|
|
import getChildRouter from './getChildRouter';
|
|
import getNavigationActionCreators from './routers/getNavigationActionCreators';
|
|
import getChildrenNavigationCache from './getChildrenNavigationCache';
|
|
|
|
const createParamGetter = route => (paramName, defaultValue) => {
|
|
const params = route.params;
|
|
|
|
if (params && paramName in params) {
|
|
return params[paramName];
|
|
}
|
|
|
|
return defaultValue;
|
|
};
|
|
|
|
function getChildNavigation(navigation, childKey, getCurrentParentNavigation) {
|
|
const children = getChildrenNavigationCache(navigation);
|
|
const childRoute = navigation.state.routes.find(r => r.key === childKey);
|
|
|
|
if (!childRoute) {
|
|
return null;
|
|
}
|
|
|
|
if (children[childKey] && children[childKey].state === childRoute) {
|
|
return children[childKey];
|
|
}
|
|
|
|
const childRouter = getChildRouter(navigation.router, childRoute.routeName);
|
|
|
|
// If the route has children, we'll use this to pass in to the action creators
|
|
// for the childRouter so that any action that depends on the active route will
|
|
// behave as expected. We don't explicitly require that routers implement routes
|
|
// and index properties, but if we did then we would put an invariant here to
|
|
// ensure that a focusedGrandChildRoute exists if childRouter is defined.
|
|
const focusedGrandChildRoute =
|
|
childRoute.routes && typeof childRoute.index === 'number'
|
|
? childRoute.routes[childRoute.index]
|
|
: null;
|
|
|
|
const actionCreators = {
|
|
...navigation.actions,
|
|
...navigation.router.getActionCreators(childRoute, navigation.state.key),
|
|
...(childRouter
|
|
? childRouter.getActionCreators(focusedGrandChildRoute, childRoute.key)
|
|
: {}),
|
|
...getNavigationActionCreators(childRoute),
|
|
};
|
|
|
|
const actionHelpers = {};
|
|
Object.keys(actionCreators).forEach(actionName => {
|
|
actionHelpers[actionName] = (...args) => {
|
|
const actionCreator = actionCreators[actionName];
|
|
const action = actionCreator(...args);
|
|
return navigation.dispatch(action);
|
|
};
|
|
});
|
|
|
|
let isFirstRouteInParent = true;
|
|
|
|
const parentNavigation = getCurrentParentNavigation();
|
|
|
|
if (parentNavigation) {
|
|
isFirstRouteInParent =
|
|
parentNavigation.state.routes.indexOf(childRoute) === 0;
|
|
}
|
|
|
|
if (
|
|
children[childKey] &&
|
|
children[childKey].isFirstRouteInParent() === isFirstRouteInParent
|
|
) {
|
|
children[childKey] = {
|
|
...children[childKey],
|
|
...actionHelpers,
|
|
state: childRoute,
|
|
router: childRouter,
|
|
actions: actionCreators,
|
|
getParam: createParamGetter(childRoute),
|
|
};
|
|
return children[childKey];
|
|
} else {
|
|
const childSubscriber = getChildEventSubscriber(
|
|
navigation.addListener,
|
|
childKey
|
|
);
|
|
|
|
children[childKey] = {
|
|
...actionHelpers,
|
|
|
|
state: childRoute,
|
|
router: childRouter,
|
|
actions: actionCreators,
|
|
getParam: createParamGetter(childRoute),
|
|
|
|
getChildNavigation: grandChildKey =>
|
|
getChildNavigation(children[childKey], grandChildKey, () => {
|
|
const nav = getCurrentParentNavigation();
|
|
return nav && nav.getChildNavigation(childKey);
|
|
}),
|
|
|
|
isFocused: () => {
|
|
const currentNavigation = getCurrentParentNavigation();
|
|
if (!currentNavigation) {
|
|
return false;
|
|
}
|
|
const { routes, index } = currentNavigation.state;
|
|
if (!currentNavigation.isFocused()) {
|
|
return false;
|
|
}
|
|
if (routes[index].key === childKey) {
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
isFirstRouteInParent: () => isFirstRouteInParent,
|
|
dispatch: navigation.dispatch,
|
|
getScreenProps: navigation.getScreenProps,
|
|
dangerouslyGetParent: getCurrentParentNavigation,
|
|
addListener: childSubscriber.addListener,
|
|
emit: childSubscriber.emit,
|
|
};
|
|
return children[childKey];
|
|
}
|
|
}
|
|
|
|
export default getChildNavigation;
|