diff --git a/packages/react-navigation/src/routers/StackRouter.js b/packages/react-navigation/src/routers/StackRouter.js index c65a3726..a16fa553 100644 --- a/packages/react-navigation/src/routers/StackRouter.js +++ b/packages/react-navigation/src/routers/StackRouter.js @@ -61,7 +61,7 @@ export default ( routeNames.forEach((routeName: string) => { let pathPattern = paths[routeName] || routeConfigs[routeName].path; const matchExact = !!pathPattern && !childRouters[routeName]; - if (!pathPattern) { + if (typeof pathPattern !== 'string') { pathPattern = routeName; } const keys = []; @@ -71,7 +71,7 @@ export default ( re = new RegExp(`(?:${re.source})|(?:${wildcardRe.source})`); } /* $FlowFixMe */ - paths[routeName] = { re, keys }; + paths[routeName] = { re, keys, toPath: pathToRegexp.compile(pathPattern) }; }); return { @@ -294,10 +294,26 @@ export default ( return state; }, - getPathAndParamsForState(): { path: string, params?: NavigationParams } { - // TODO: implement this! + getPathAndParamsForState( + state: NavigationState, + ): { path: string, params?: NavigationParams } { + const route = state.routes[state.index]; + const routeName = route.routeName; + const screen = getScreenForRouteName(routeConfigs, routeName); + /* $FlowFixMe */ + const subPath = paths[routeName].toPath(route.params); + let path = subPath; + let params = route.params; + if (screen && screen.router) { + // If it has a router it's a navigator. + // If it doesn't have router it's an ordinary React component. + const child = screen.router.getPathAndParamsForState(route); + path = subPath ? `${subPath}/${child.path}` : child.path; + params = child.params ? { ...params, ...child.params } : params; + } return { - path: '', + path, + params, }; }, diff --git a/packages/react-navigation/src/routers/__tests__/StackRouter-test.js b/packages/react-navigation/src/routers/__tests__/StackRouter-test.js index 83f060b5..0c60447f 100644 --- a/packages/react-navigation/src/routers/__tests__/StackRouter-test.js +++ b/packages/react-navigation/src/routers/__tests__/StackRouter-test.js @@ -821,6 +821,49 @@ describe('StackRouter', () => { expect(state && state.routes[0]).toEqual({ key: 'Init', routeName: 'Bar' }); }); + test('Gets deep path', () => { + const ScreenA = () =>
; + const ScreenB = () =>
; + ScreenA.router = StackRouter({ + Boo: { path: 'boo', screen: ScreenB }, + Baz: { path: 'baz/:bazId', screen: ScreenB }, + }); + const router = StackRouter({ + Foo: { + path: 'f/:id', + screen: ScreenA, + }, + Bar: { + screen: ScreenB, + }, + }); + + const state = { + index: 0, + routes: [ + { + index: 1, + key: 'Foo', + routeName: 'Foo', + params: { + id: '123', + }, + routes: [ + { key: 'Boo', routeName: 'Boo' }, + { key: 'Baz', routeName: 'Baz', params: { bazId: '321' } }, + ], + }, + { key: 'Bar', routeName: 'Bar' }, + ], + }; + const { path, params } = router.getPathAndParamsForState(state); + expect(path).toEqual('f/123/baz/321'); + /* $FlowFixMe: params.id has to exist */ + expect(params.id).toEqual('123'); + /* $FlowFixMe: params.bazId has to exist */ + expect(params.bazId).toEqual('321'); + }); + test('Maps old actions (uses "Handles the reset action" test)', () => { const router = StackRouter({ Foo: {