diff --git a/flow/react-navigation.js b/flow/react-navigation.js index b6c2de7a91..388da5cc09 100644 --- a/flow/react-navigation.js +++ b/flow/react-navigation.js @@ -405,6 +405,7 @@ declare module 'react-navigation' { initialRouteParams?: NavigationParams, paths?: NavigationPathsConfig, navigationOptions?: NavigationScreenConfig<*>, + initialRouteKey?: 'initialRouteName' | 'generated', |}; declare export type NavigationStackViewConfig = {| diff --git a/src/routers/StackRouter.js b/src/routers/StackRouter.js index 5c9c2afcc6..f1ba2b5827 100644 --- a/src/routers/StackRouter.js +++ b/src/routers/StackRouter.js @@ -92,11 +92,16 @@ export default (routeConfigs, stackConfig = {}) => { ...(action.params || {}), ...(initialRouteParams || {}), }; + const { initialRouteKey } = stackConfig; route = { ...route, ...(params ? { params } : {}), routeName: initialRouteName, - key: action.key || generateKey(), + key: + action.key || + (initialRouteKey && initialRouteKey === 'initialRouteName' + ? initialRouteName + : generateKey()), }; return { key: 'StackRouterRoot', diff --git a/src/routers/__tests__/Routers-test.js b/src/routers/__tests__/Routers-test.js index 8a525c1cfc..021a730bda 100644 --- a/src/routers/__tests__/Routers-test.js +++ b/src/routers/__tests__/Routers-test.js @@ -110,8 +110,8 @@ test('Handles no-op actions with tabs within stack router', () => { type: NavigationActions.NAVIGATE, routeName: 'Qux', }); - expect(state1.routes[0].key).toEqual('Foo'); - expect(state2.routes[0].key).toEqual('Foo'); + expect(state1.routes[0].key).toEqual('id-0'); + expect(state2.routes[0].key).toEqual('id-1'); state1.routes[0].key = state2.routes[0].key; expect(state1).toEqual(state2); const state3 = TestRouter.getStateForAction( @@ -139,7 +139,7 @@ test('Handles deep action', () => { key: 'StackRouterRoot', routes: [ { - key: 'Bar', + key: 'id-0', routeName: 'Bar', }, ], @@ -179,7 +179,9 @@ test('Supports lazily-evaluated getScreen', () => { immediate: true, routeName: 'Qux', }); - expect(state1.routes[0].key).toEqual('Foo'); + expect(state1.routes[0].key).toEqual('id-0'); + expect(state2.routes[0].key).toEqual('id-1'); + state1.routes[0].key = state2.routes[0].key; expect(state1).toEqual(state2); const state3 = TestRouter.getStateForAction( { diff --git a/src/routers/__tests__/StackRouter-test.js b/src/routers/__tests__/StackRouter-test.js index f1fd385cbc..a4c46b87d2 100644 --- a/src/routers/__tests__/StackRouter-test.js +++ b/src/routers/__tests__/StackRouter-test.js @@ -355,7 +355,7 @@ describe('StackRouter', () => { index: 0, isTransitioning: false, key: 'StackRouterRoot', - routes: [{ key: 'foo', routeName: 'foo' }], + routes: [{ key: 'id-0', routeName: 'foo' }], }); const pushedState = TestRouter.getStateForAction( NavigationActions.navigate({ routeName: 'qux' }), @@ -547,6 +547,23 @@ describe('StackRouter', () => { expect(state2.routes[1].routes[1].routes[1].routeName).toEqual('Corge'); }); + test('Navigate to initial screen is possible', () => { + const TestRouter = StackRouter( + { + foo: { screen: () =>
}, + bar: { screen: () =>
}, + }, + { initialRouteKey: 'initialRouteName' } + ); + const initState = TestRouter.getStateForAction(NavigationActions.init()); + const pushedState = TestRouter.getStateForAction( + NavigationActions.navigate({ routeName: 'foo', key: 'foo' }), + initState + ); + expect(pushedState.index).toEqual(0); + expect(pushedState.routes[0].routeName).toEqual('foo'); + }); + test('Navigate with key is idempotent', () => { const TestRouter = StackRouter({ foo: { screen: () =>
}, @@ -636,7 +653,7 @@ describe('StackRouter', () => { key: 'StackRouterRoot', routes: [ { - key: 'Foo', + key: 'id-0', routeName: 'Foo', }, ], @@ -664,7 +681,7 @@ describe('StackRouter', () => { key: 'StackRouterRoot', routes: [ { - key: 'Foo', + key: 'id-0', routeName: 'Foo', }, ], @@ -761,7 +778,7 @@ describe('StackRouter', () => { key: 'StackRouterRoot', routes: [ { - key: 'Foo', + key: 'id-0', routeName: 'Foo', }, ], @@ -789,7 +806,7 @@ describe('StackRouter', () => { key: 'StackRouterRoot', routes: [ { - key: 'Foo', + key: 'id-0', routeName: 'Foo', }, ], @@ -863,7 +880,7 @@ describe('StackRouter', () => { key: 'StackRouterRoot', routes: [ { - key: 'Bar', + key: 'id-0', routeName: 'Bar', }, ], @@ -972,14 +989,14 @@ describe('StackRouter', () => { { type: NavigationActions.SET_PARAMS, params: { name: 'foobar' }, - key: 'Quux', + key: 'id-0', }, state ); expect(state2 && state2.index).toEqual(0); expect(state2 && state2.routes[0].routes[0].routes).toEqual([ { - key: 'Quux', + key: 'id-0', routeName: 'Quux', params: { name: 'foobar' }, },