Don't delegate inner action to child router, handle inner action when handling NAVIGATE

This commit is contained in:
Patrick Monteith
2017-04-03 10:51:19 +01:00
parent bffb9d17ff
commit 8d0f086a8a
2 changed files with 74 additions and 6 deletions

View File

@@ -61,11 +61,9 @@ export default (
const routes = order.map((routeName: string) => {
const tabRouter = tabRouters[routeName];
if (tabRouter) {
const childAction =
action.action ||
NavigationActions.init({
...(action.params ? { params: action.params } : {}),
});
const childAction = NavigationActions.init({
...(action.params ? { params: action.params } : {}),
});
return {
...tabRouter.getStateForAction(childAction),
key: routeName,
@@ -106,7 +104,7 @@ export default (
const activeTabRouter = tabRouters[order[state.index]];
if (activeTabRouter) {
const activeTabState = activeTabRouter.getStateForAction(
action.action || action,
action,
activeTabLastState
);
if (!activeTabState && inputState) {

View File

@@ -3,9 +3,12 @@
import React from 'react';
import TabRouter from '../TabRouter';
import StackRouter from '../StackRouter';
import NavigationActions from '../../NavigationActions';
import type { NavigationRoute, NavigationState } from '../../TypeDefinition';
const INIT_ACTION = { type: NavigationActions.INIT };
const BareLeafRouteConfig = {
@@ -604,4 +607,71 @@ describe('TabRouter', () => {
],
});
});
test('Inner actions are only unpacked if the current tab matches', () => {
const PlainScreen = () => <div />;
const ScreenA = () => <div />;
const ScreenB = () => <div />;
ScreenB.router = StackRouter({
Baz: { screen: PlainScreen },
Zoo: { screen: PlainScreen },
});
ScreenA.router = StackRouter({
Bar: { screen: PlainScreen },
Boo: { screen: ScreenB },
});
const router = TabRouter({
Foo: { screen: ScreenA },
});
const screenApreState = {
index: 0,
key: 'Init',
routeName: 'Foo',
routes: [{ key: 'Init', routeName: 'Bar' }],
};
const preState = {
index: 0,
routes: [screenApreState],
};
type ComparableRoute = {
routeName?: string,
routes?: Array<ComparableRoute>,
};
type RouteOrState =
| NavigationRoute
| NavigationState
| (NavigationRoute & NavigationState);
const comparable = (state: RouteOrState): ComparableRoute => {
let result = {};
if (typeof state.routeName === 'string') {
result = { ...result, routeName: state.routeName };
}
if (state.routes instanceof Array) {
result = {
...result,
routes: state.routes.map(comparable),
};
}
return result;
};
const action = NavigationActions.navigate({
routeName: 'Boo',
action: NavigationActions.navigate({ routeName: 'Zoo' }),
});
const expectedState = ScreenA.router.getStateForAction(
action,
screenApreState
);
const state = router.getStateForAction(action, preState);
const innerState = state ? state.routes[0] : state;
expect(expectedState && comparable(expectedState)).toEqual(
innerState && comparable(innerState)
);
});
});