From 8d0f086a8a4871a5be5fd50d2b6a4f5df540f1e2 Mon Sep 17 00:00:00 2001 From: Patrick Monteith Date: Mon, 3 Apr 2017 10:51:19 +0100 Subject: [PATCH] Don't delegate inner action to child router, handle inner action when handling NAVIGATE --- .../react-navigation/src/routers/TabRouter.js | 10 ++- .../src/routers/__tests__/TabRouter-test.js | 70 +++++++++++++++++++ 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/packages/react-navigation/src/routers/TabRouter.js b/packages/react-navigation/src/routers/TabRouter.js index 37550755..8ed3ec1c 100644 --- a/packages/react-navigation/src/routers/TabRouter.js +++ b/packages/react-navigation/src/routers/TabRouter.js @@ -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) { diff --git a/packages/react-navigation/src/routers/__tests__/TabRouter-test.js b/packages/react-navigation/src/routers/__tests__/TabRouter-test.js index f3c87147..4712cbd7 100644 --- a/packages/react-navigation/src/routers/__tests__/TabRouter-test.js +++ b/packages/react-navigation/src/routers/__tests__/TabRouter-test.js @@ -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 = () =>
; + const ScreenA = () =>
; + const ScreenB = () =>
; + 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, + }; + + 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) + ); + }); });