diff --git a/packages/react-navigation/src/routers/StackRouter.js b/packages/react-navigation/src/routers/StackRouter.js index 5f6f7dbd..779f1c76 100644 --- a/packages/react-navigation/src/routers/StackRouter.js +++ b/packages/react-navigation/src/routers/StackRouter.js @@ -255,12 +255,11 @@ export default (routeConfigs, stackConfig = {}) => { // active route has the first opportunity, then the one before it, etc. for (let childRoute of state.routes.slice().reverse()) { let childRouter = childRouters[childRoute.routeName]; - let debug = action.params && action.params.debug; - let childAction = action.routeName === childRoute.routeName && action.action ? action.action : action; + if (childRouter) { const nextRouteState = childRouter.getStateForAction( childAction, diff --git a/packages/react-navigation/src/routers/__tests__/StackRouter-test.js b/packages/react-navigation/src/routers/__tests__/StackRouter-test.js index 1bb80792..b71dea86 100644 --- a/packages/react-navigation/src/routers/__tests__/StackRouter-test.js +++ b/packages/react-navigation/src/routers/__tests__/StackRouter-test.js @@ -1850,3 +1850,120 @@ test('Handles deep navigate completion action', () => { expect(state3 && state3.routes[0].index).toEqual(1); expect(state3 && state3.routes[0].isTransitioning).toEqual(false); }); + +test('order of handling navigate action is correct for nested stackrouters', () => { + const Screen = () =>
; + const NestedStack = () => ; + let nestedRouter = StackRouter({ + Foo: Screen, + Bar: Screen, + }); + + NestedStack.router = nestedRouter; + + let router = StackRouter( + { + NestedStack, + Bar: Screen, + Baz: Screen, + }, + { + initialRouteName: 'Baz', + } + ); + + const state = router.getStateForAction({ type: NavigationActions.INIT }); + expect(state.routes[state.index].routeName).toEqual('Baz'); + + const state2 = router.getStateForAction( + { + type: NavigationActions.NAVIGATE, + routeName: 'Bar', + }, + state + ); + expect(state2.routes[state2.index].routeName).toEqual('Bar'); + + const state3 = router.getStateForAction( + { + type: NavigationActions.NAVIGATE, + routeName: 'Baz', + }, + state2 + ); + expect(state3.routes[state3.index].routeName).toEqual('Baz'); + + const state4 = router.getStateForAction( + { + type: NavigationActions.NAVIGATE, + routeName: 'Foo', + }, + state3 + ); + let activeState4 = state4.routes[state4.index]; + expect(activeState4.routeName).toEqual('NestedStack'); + expect(activeState4.routes[activeState4.index].routeName).toEqual('Foo'); + + const state5 = router.getStateForAction( + { + type: NavigationActions.NAVIGATE, + routeName: 'Bar', + }, + state4 + ); + let activeState5 = state5.routes[state5.index]; + expect(activeState5.routeName).toEqual('NestedStack'); + expect(activeState5.routes[activeState5.index].routeName).toEqual('Bar'); +}); + +test('order of handling navigate action is correct for nested stackrouters', () => { + const Screen = () => ; + const NestedStack = () => ; + const OtherNestedStack = () => ; + + let nestedRouter = StackRouter({ Foo: Screen, Bar: Screen }); + let otherNestedRouter = StackRouter({ Foo: Screen }); + NestedStack.router = nestedRouter; + OtherNestedStack.router = otherNestedRouter; + + let router = StackRouter( + { + NestedStack, + OtherNestedStack, + Bar: Screen, + }, + { + initialRouteName: 'OtherNestedStack', + } + ); + + const state = router.getStateForAction({ type: NavigationActions.INIT }); + expect(state.routes[state.index].routeName).toEqual('OtherNestedStack'); + + const state2 = router.getStateForAction( + { + type: NavigationActions.NAVIGATE, + routeName: 'Bar', + }, + state + ); + expect(state2.routes[state2.index].routeName).toEqual('Bar'); + + const state3 = router.getStateForAction( + { + type: NavigationActions.NAVIGATE, + routeName: 'NestedStack', + }, + state2 + ); + const state4 = router.getStateForAction( + { + type: NavigationActions.NAVIGATE, + routeName: 'Bar', + }, + state3 + ); + let activeState4 = state4.routes[state4.index]; + expect(activeState4.routeName).toEqual('NestedStack'); + expect(activeState4.routes[activeState4.index].routeName).toEqual('Bar'); +}); diff --git a/packages/react-navigation/src/routers/__tests__/SwitchRouter-test.js b/packages/react-navigation/src/routers/__tests__/SwitchRouter-test.js index 04929465..198a291f 100644 --- a/packages/react-navigation/src/routers/__tests__/SwitchRouter-test.js +++ b/packages/react-navigation/src/routers/__tests__/SwitchRouter-test.js @@ -127,6 +127,96 @@ describe('SwitchRouter', () => { }, }); }); + + test('order of handling navigate action is correct for nested switchrouters', () => { + // router = switch({ Nested: switch({ Foo, Bar }), Other: switch({ Foo }), Bar }) + // if we are focused on Other and navigate to Bar, what should happen? + + const Screen = () => ; + const NestedSwitch = () => ; + const OtherNestedSwitch = () => ; + + let nestedRouter = SwitchRouter({ Foo: Screen, Bar: Screen }); + let otherNestedRouter = SwitchRouter({ Foo: Screen }); + NestedSwitch.router = nestedRouter; + OtherNestedSwitch.router = otherNestedRouter; + + let router = SwitchRouter( + { + NestedSwitch, + OtherNestedSwitch, + Bar: Screen, + }, + { + initialRouteName: 'OtherNestedSwitch', + } + ); + + const state = router.getStateForAction({ type: NavigationActions.INIT }); + expect(state.routes[state.index].routeName).toEqual('OtherNestedSwitch'); + + const state2 = router.getStateForAction( + { + type: NavigationActions.NAVIGATE, + routeName: 'Bar', + }, + state + ); + expect(state2.routes[state2.index].routeName).toEqual('Bar'); + + const state3 = router.getStateForAction( + { + type: NavigationActions.NAVIGATE, + routeName: 'NestedSwitch', + }, + state2 + ); + const state4 = router.getStateForAction( + { + type: NavigationActions.NAVIGATE, + routeName: 'Bar', + }, + state3 + ); + let activeState4 = state4.routes[state4.index]; + expect(activeState4.routeName).toEqual('NestedSwitch'); + expect(activeState4.routes[activeState4.index].routeName).toEqual('Bar'); + }); + + test('order of handling navigate action is correct for nested stackrouters', () => { + // router = switch({ Nested: switch({ Foo, Bar }), Other: switch({ Foo }), Bar }) + // if we are focused on Other and navigate to Bar, what should happen? + + const Screen = () => ; + + const MainStack = () => ; + const LoginStack = () => ; + MainStack.router = StackRouter({ Home: Screen, Profile: Screen }); + LoginStack.router = StackRouter({ Form: Screen, ForgotPassword: Screen }); + + let router = SwitchRouter( + { + Home: Screen, + Login: LoginStack, + Main: MainStack, + }, + { + initialRouteName: 'Login', + } + ); + + const state = router.getStateForAction({ type: NavigationActions.INIT }); + expect(state.routes[state.index].routeName).toEqual('Login'); + + const state2 = router.getStateForAction( + { + type: NavigationActions.NAVIGATE, + routeName: 'Home', + }, + state + ); + expect(state2.routes[state2.index].routeName).toEqual('Home'); + }); }); const getExampleRouter = (config = {}) => {