diff --git a/packages/core/src/__tests__/BaseNavigationContainer.test.tsx b/packages/core/src/__tests__/BaseNavigationContainer.test.tsx index 71c9dd1676..20248af2da 100644 --- a/packages/core/src/__tests__/BaseNavigationContainer.test.tsx +++ b/packages/core/src/__tests__/BaseNavigationContainer.test.tsx @@ -1,10 +1,6 @@ import * as React from 'react'; import { act, render } from 'react-native-testing-library'; -import { - DefaultRouterOptions, - NavigationState, - Router, -} from '@react-navigation/routers'; +import { NavigationState, Router } from '@react-navigation/routers'; import BaseNavigationContainer from '../BaseNavigationContainer'; import NavigationStateContext from '../NavigationStateContext'; import MockRouter, { MockActions } from './__fixtures__/MockRouter'; @@ -79,8 +75,8 @@ it('throws when nesting containers', () => { it('handle dispatching with ref', () => { const CurrentParentRouter = MockRouter; - function CurrentChildRouter(options: DefaultRouterOptions) { - const CurrentMockRouter = MockRouter(options); + function CurrentChildRouter() { + const CurrentMockRouter = MockRouter(); const ChildRouter: Router< NavigationState, MockActions | { type: 'REVERSE' } diff --git a/packages/core/src/__tests__/__fixtures__/MockRouter.tsx b/packages/core/src/__tests__/__fixtures__/MockRouter.tsx index 62cc622903..5ad03b016c 100644 --- a/packages/core/src/__tests__/__fixtures__/MockRouter.tsx +++ b/packages/core/src/__tests__/__fixtures__/MockRouter.tsx @@ -4,22 +4,21 @@ import { CommonNavigationAction, NavigationState, Route, - DefaultRouterOptions, } from '@react-navigation/routers'; export type MockActions = CommonNavigationAction | { type: 'NOOP' | 'UPDATE' }; export const MockRouterKey = { current: 0 }; -export default function MockRouter(options: DefaultRouterOptions) { +export default function MockRouter() { const router: Router = { type: 'test', - getInitialState({ routeNames, routeParamList }) { + getInitialState({ initialRouteName, routeNames, routeParamList }) { const index = - options.initialRouteName === undefined + initialRouteName === undefined ? 0 - : routeNames.indexOf(options.initialRouteName); + : routeNames.indexOf(initialRouteName); return { stale: false, diff --git a/packages/core/src/__tests__/index.test.tsx b/packages/core/src/__tests__/index.test.tsx index e91788fe23..ca2bd937b6 100644 --- a/packages/core/src/__tests__/index.test.tsx +++ b/packages/core/src/__tests__/index.test.tsx @@ -742,8 +742,8 @@ it('navigates to nested child in a navigator', () => { }); it('navigates to nested child in a navigator with initial: false', () => { - const TestRouter: typeof MockRouter = (options) => { - const router = MockRouter(options); + const TestRouter: typeof MockRouter = () => { + const router = MockRouter(); return { ...router, diff --git a/packages/core/src/__tests__/useDescriptors.test.tsx b/packages/core/src/__tests__/useDescriptors.test.tsx index 7def6b1f3d..7b1e077dda 100644 --- a/packages/core/src/__tests__/useDescriptors.test.tsx +++ b/packages/core/src/__tests__/useDescriptors.test.tsx @@ -1,10 +1,6 @@ import * as React from 'react'; import { render, act } from 'react-native-testing-library'; -import { - DefaultRouterOptions, - NavigationState, - Router, -} from '@react-navigation/routers'; +import { NavigationState, Router } from '@react-navigation/routers'; import useNavigationBuilder from '../useNavigationBuilder'; import BaseNavigationContainer from '../BaseNavigationContainer'; import Screen from '../Screen'; @@ -420,8 +416,8 @@ it("returns correct value for canGoBack when it's not overridden", () => { }); it(`returns false for canGoBack when current router doesn't handle GO_BACK`, () => { - function TestRouter(options: DefaultRouterOptions) { - const CurrentMockRouter = MockRouter(options); + function TestRouter() { + const CurrentMockRouter = MockRouter(); const ChildRouter: Router = { ...CurrentMockRouter, @@ -471,8 +467,8 @@ it(`returns false for canGoBack when current router doesn't handle GO_BACK`, () }); it('returns true for canGoBack when current router handles GO_BACK', () => { - function ParentRouter(options: DefaultRouterOptions) { - const CurrentMockRouter = MockRouter(options); + function ParentRouter() { + const CurrentMockRouter = MockRouter(); const ChildRouter: Router = { ...CurrentMockRouter, @@ -538,8 +534,8 @@ it('returns true for canGoBack when current router handles GO_BACK', () => { }); it('returns true for canGoBack when parent router handles GO_BACK', () => { - function OverrodeRouter(options: DefaultRouterOptions) { - const CurrentMockRouter = MockRouter(options); + function OverrodeRouter() { + const CurrentMockRouter = MockRouter(); const ChildRouter: Router = { ...CurrentMockRouter, diff --git a/packages/core/src/__tests__/useEventEmitter.test.tsx b/packages/core/src/__tests__/useEventEmitter.test.tsx index a505e3f44f..ca070e2e13 100644 --- a/packages/core/src/__tests__/useEventEmitter.test.tsx +++ b/packages/core/src/__tests__/useEventEmitter.test.tsx @@ -296,17 +296,19 @@ it('fires focus and blur events in nested navigator', () => { }); it('fires blur event when a route is removed with a delay', async () => { - const TestRouter = (options: any): Router => { - const router = MockRouter(options); + const TestRouter = (): Router => { + const router = MockRouter(); return { ...router, - getInitialState({ routeNames, routeParamList }) { + getInitialState({ + initialRouteName: _initialRouteName, + routeNames, + routeParamList, + }) { const initialRouteName = - options.initialRouteName !== undefined - ? options.initialRouteName - : routeNames[0]; + _initialRouteName !== undefined ? _initialRouteName : routeNames[0]; return { stale: false, diff --git a/packages/core/src/__tests__/useNavigationCache.test.tsx b/packages/core/src/__tests__/useNavigationCache.test.tsx index 59a4ac2ceb..226890c2ae 100644 --- a/packages/core/src/__tests__/useNavigationCache.test.tsx +++ b/packages/core/src/__tests__/useNavigationCache.test.tsx @@ -27,7 +27,7 @@ it('preserves reference for navigation objects', () => { const getState = () => state; const navigation = {} as any; const setOptions = (() => {}) as any; - const router = MockRouter({}); + const router = MockRouter(); const Test = () => { const previous = React.useRef(); @@ -101,10 +101,8 @@ it('returns correct value for isFocused', () => { }); it('returns correct value for isFocused after changing screens', () => { - const TestRouter = ( - options: Parameters[0] - ): ReturnType => { - const router = MockRouter(options); + const TestRouter = (): ReturnType => { + const router = MockRouter(); return { ...router, diff --git a/packages/core/src/__tests__/useOnAction.test.tsx b/packages/core/src/__tests__/useOnAction.test.tsx index ee99676d9a..4de11ae4c2 100644 --- a/packages/core/src/__tests__/useOnAction.test.tsx +++ b/packages/core/src/__tests__/useOnAction.test.tsx @@ -1,10 +1,6 @@ import * as React from 'react'; import { render } from 'react-native-testing-library'; -import { - Router, - DefaultRouterOptions, - NavigationState, -} from '@react-navigation/routers'; +import { Router, NavigationState } from '@react-navigation/routers'; import useNavigationBuilder from '../useNavigationBuilder'; import BaseNavigationContainer from '../BaseNavigationContainer'; import Screen from '../Screen'; @@ -16,8 +12,8 @@ import MockRouter, { beforeEach(() => (MockRouterKey.current = 0)); it("lets parent handle the action if child didn't", () => { - function CurrentRouter(options: DefaultRouterOptions) { - const CurrentMockRouter = MockRouter(options); + function CurrentRouter() { + const CurrentMockRouter = MockRouter(); const ParentRouter: Router< NavigationState, MockActions | { type: 'REVERSE' } @@ -95,8 +91,8 @@ it("lets parent handle the action if child didn't", () => { it("lets children handle the action if parent didn't", () => { const CurrentParentRouter = MockRouter; - function CurrentChildRouter(options: DefaultRouterOptions) { - const CurrentMockRouter = MockRouter(options); + function CurrentChildRouter() { + const CurrentMockRouter = MockRouter(); const ChildRouter: Router< NavigationState, MockActions | { type: 'REVERSE' } @@ -227,8 +223,8 @@ it("lets children handle the action if parent didn't", () => { it("action doesn't bubble if target is specified", () => { const CurrentParentRouter = MockRouter; - function CurrentChildRouter(options: DefaultRouterOptions) { - const CurrentMockRouter = MockRouter(options); + function CurrentChildRouter() { + const CurrentMockRouter = MockRouter(); const ChildRouter: Router< NavigationState, MockActions | { type: 'REVERSE' } diff --git a/packages/core/src/useNavigationBuilder.tsx b/packages/core/src/useNavigationBuilder.tsx index 7c98972ff0..d627b29cb5 100644 --- a/packages/core/src/useNavigationBuilder.tsx +++ b/packages/core/src/useNavigationBuilder.tsx @@ -179,17 +179,20 @@ export default function useNavigationBuilder< }, [route]); const { children, ...rest } = options; + const routerOptions = { + ...((rest as unknown) as RouterOptions), + ...(route?.params && + route.params.initial !== false && + typeof route.params.screen === 'string' + ? { initialRouteName: route.params.screen } + : null), + }; const { current: router } = React.useRef>( - createRouter({ - ...((rest as unknown) as RouterOptions), - ...(route?.params && - route.params.initial !== false && - typeof route.params.screen === 'string' - ? { initialRouteName: route.params.screen } - : null), - }) + createRouter(routerOptions) ); + const { initialRouteName } = routerOptions; + const routeConfigs = getRouteConfigsFromChildren< State, ScreenOptions, @@ -267,6 +270,7 @@ export default function useNavigationBuilder< if (currentState === undefined || !isStateValid(currentState)) { return [ router.getInitialState({ + initialRouteName, routeNames, routeParamList, }), @@ -275,6 +279,7 @@ export default function useNavigationBuilder< } else { return [ router.getRehydratedState(currentState as PartialState, { + initialRouteName, routeNames, routeParamList, }), @@ -303,6 +308,7 @@ export default function useNavigationBuilder< if (!isArrayEqual(state.routeNames, routeNames)) { // When the list of route names change, the router should handle it to remove invalid routes nextState = router.getStateForRouteNamesChange(state, { + initialRouteName, routeNames, routeParamList, }); @@ -327,6 +333,7 @@ export default function useNavigationBuilder< nextState = updatedState !== null ? router.getRehydratedState(updatedState, { + initialRouteName, routeNames, routeParamList, }) @@ -448,6 +455,7 @@ export default function useNavigationBuilder< key: route?.key, listeners: actionListeners, routerConfigOptions: { + initialRouteName, routeNames, routeParamList, }, diff --git a/packages/routers/src/DrawerRouter.tsx b/packages/routers/src/DrawerRouter.tsx index aa657f1d0d..0e3419b652 100644 --- a/packages/routers/src/DrawerRouter.tsx +++ b/packages/routers/src/DrawerRouter.tsx @@ -100,7 +100,7 @@ const closeDrawer = (state: DrawerNavigationState): DrawerNavigationState => { export default function DrawerRouter({ openByDefault, ...rest -}: DrawerRouterOptions): Router< +}: DrawerRouterOptions = {}): Router< DrawerNavigationState, DrawerActionType | CommonNavigationAction > { @@ -114,8 +114,8 @@ export default function DrawerRouter({ type: 'drawer', - getInitialState({ routeNames, routeParamList }) { - let state = router.getInitialState({ routeNames, routeParamList }); + getInitialState(configOptions) { + let state = router.getInitialState(configOptions); if (openByDefault) { state = openDrawer(state); @@ -129,15 +129,12 @@ export default function DrawerRouter({ }; }, - getRehydratedState(partialState, { routeNames, routeParamList }) { + getRehydratedState(partialState, configOptions) { if (partialState.stale === false) { return partialState; } - let state = router.getRehydratedState(partialState, { - routeNames, - routeParamList, - }); + let state = router.getRehydratedState(partialState, configOptions); if (isDrawerOpen(partialState)) { state = openDrawer(state); @@ -160,7 +157,7 @@ export default function DrawerRouter({ return closeDrawer(result); }, - getStateForAction(state, action, options) { + getStateForAction(state, action, configOptions) { switch (action.type) { case 'OPEN_DRAWER': return openDrawer(state); @@ -186,10 +183,10 @@ export default function DrawerRouter({ } } - return router.getStateForAction(state, action, options); + return router.getStateForAction(state, action, configOptions); default: - return router.getStateForAction(state, action, options); + return router.getStateForAction(state, action, configOptions); } }, diff --git a/packages/routers/src/StackRouter.tsx b/packages/routers/src/StackRouter.tsx index 329c2afef6..3d3e8a66ab 100644 --- a/packages/routers/src/StackRouter.tsx +++ b/packages/routers/src/StackRouter.tsx @@ -94,7 +94,7 @@ export const StackActions = { }, }; -export default function StackRouter(options: StackRouterOptions) { +export default function StackRouter() { const router: Router< StackNavigationState, CommonNavigationAction | StackActionType @@ -103,11 +103,15 @@ export default function StackRouter(options: StackRouterOptions) { type: 'stack', - getInitialState({ routeNames, routeParamList }) { + getInitialState({ + initialRouteName: _initialRouteName, + routeNames, + routeParamList, + }) { const initialRouteName = - options.initialRouteName !== undefined && - routeNames.includes(options.initialRouteName) - ? options.initialRouteName + _initialRouteName !== undefined && + routeNames.includes(_initialRouteName) + ? _initialRouteName : routeNames[0]; return { @@ -126,7 +130,10 @@ export default function StackRouter(options: StackRouterOptions) { }; }, - getRehydratedState(partialState, { routeNames, routeParamList }) { + getRehydratedState( + partialState, + { initialRouteName: _initialRouteName, routeNames, routeParamList } + ) { let state = partialState; if (state.stale === false) { @@ -152,9 +159,7 @@ export default function StackRouter(options: StackRouterOptions) { if (routes.length === 0) { const initialRouteName = - options.initialRouteName !== undefined - ? options.initialRouteName - : routeNames[0]; + _initialRouteName !== undefined ? _initialRouteName : routeNames[0]; routes.push({ key: `${initialRouteName}-${nanoid()}`, @@ -173,16 +178,19 @@ export default function StackRouter(options: StackRouterOptions) { }; }, - getStateForRouteNamesChange(state, { routeNames, routeParamList }) { + getStateForRouteNamesChange( + state, + { initialRouteName: _initialRouteName, routeNames, routeParamList } + ) { const routes = state.routes.filter((route) => routeNames.includes(route.name) ); if (routes.length === 0) { const initialRouteName = - options.initialRouteName !== undefined && - routeNames.includes(options.initialRouteName) - ? options.initialRouteName + _initialRouteName !== undefined && + routeNames.includes(_initialRouteName) + ? _initialRouteName : routeNames[0]; routes.push({ diff --git a/packages/routers/src/TabRouter.tsx b/packages/routers/src/TabRouter.tsx index 77ce24d414..25ae4f1d2c 100644 --- a/packages/routers/src/TabRouter.tsx +++ b/packages/routers/src/TabRouter.tsx @@ -123,9 +123,9 @@ const changeIndex = ( }; export default function TabRouter({ - initialRouteName, backBehavior = 'history', -}: TabRouterOptions) { + ...options +}: TabRouterOptions = {}) { const router: Router< TabNavigationState, TabActionType | CommonNavigationAction @@ -134,7 +134,7 @@ export default function TabRouter({ type: 'tab', - getInitialState({ routeNames, routeParamList }) { + getInitialState({ initialRouteName, routeNames, routeParamList }) { const index = initialRouteName !== undefined && routeNames.includes(initialRouteName) ? routeNames.indexOf(initialRouteName) @@ -164,7 +164,10 @@ export default function TabRouter({ }; }, - getRehydratedState(partialState, { routeNames, routeParamList }) { + getRehydratedState( + partialState, + { initialRouteName, routeNames, routeParamList } + ) { let state = partialState; if (state.stale === false) { @@ -229,7 +232,10 @@ export default function TabRouter({ }; }, - getStateForRouteNamesChange(state, { routeNames, routeParamList }) { + getStateForRouteNamesChange( + state, + { initialRouteName, routeNames, routeParamList } + ) { const routes = routeNames.map( (name) => state.routes.find((r) => r.name === name) || { @@ -275,10 +281,10 @@ export default function TabRouter({ return state; } - return changeIndex(state, index, backBehavior, initialRouteName); + return changeIndex(state, index, backBehavior, options.initialRouteName); }, - getStateForAction(state, action) { + getStateForAction(state, action, { initialRouteName }) { switch (action.type) { case 'JUMP_TO': case 'NAVIGATE': { diff --git a/packages/routers/src/__tests__/DrawerRouter.test.tsx b/packages/routers/src/__tests__/DrawerRouter.test.tsx index 4ec95b9058..57b286b602 100644 --- a/packages/routers/src/__tests__/DrawerRouter.test.tsx +++ b/packages/routers/src/__tests__/DrawerRouter.test.tsx @@ -12,6 +12,7 @@ it('gets initial state from route names and params with initialRouteName', () => expect( router.getInitialState({ + initialRouteName: 'baz', routeNames: ['bar', 'baz', 'qux'], routeParamList: { baz: { answer: 42 }, @@ -34,7 +35,7 @@ it('gets initial state from route names and params with initialRouteName', () => }); it('gets initial state from route names and params without initialRouteName', () => { - const router = DrawerRouter({}); + const router = DrawerRouter(); expect( router.getInitialState({ @@ -60,7 +61,7 @@ it('gets initial state from route names and params without initialRouteName', () }); it('gets rehydrated state from partial state', () => { - const router = DrawerRouter({}); + const router = DrawerRouter(); const options = { routeNames: ['bar', 'baz', 'qux'], @@ -197,7 +198,7 @@ it('gets rehydrated state from partial state', () => { }); it("doesn't rehydrate state if it's not stale", () => { - const router = DrawerRouter({}); + const router = DrawerRouter(); const state: DrawerNavigationState = { index: 0, @@ -222,7 +223,7 @@ it("doesn't rehydrate state if it's not stale", () => { }); it('handles navigate action', () => { - const router = DrawerRouter({}); + const router = DrawerRouter(); const options = { routeNames: ['baz', 'bar'], routeParamList: {}, @@ -263,7 +264,7 @@ it('handles navigate action', () => { }); it('handles navigate action with open drawer', () => { - const router = DrawerRouter({}); + const router = DrawerRouter(); const options = { routeNames: ['baz', 'bar'], routeParamList: {}, @@ -304,7 +305,7 @@ it('handles navigate action with open drawer', () => { }); it('handles open drawer action', () => { - const router = DrawerRouter({}); + const router = DrawerRouter(); const options = { routeNames: ['baz', 'bar'], routeParamList: {}, @@ -359,7 +360,7 @@ it('handles open drawer action', () => { }); it('handles close drawer action', () => { - const router = DrawerRouter({}); + const router = DrawerRouter(); const options = { routeNames: ['baz', 'bar'], routeParamList: {}, @@ -417,7 +418,7 @@ it('handles close drawer action', () => { }); it('handles toggle drawer action', () => { - const router = DrawerRouter({}); + const router = DrawerRouter(); const options = { routeNames: ['baz', 'bar'], routeParamList: {}, diff --git a/packages/routers/src/__tests__/StackRouter.test.tsx b/packages/routers/src/__tests__/StackRouter.test.tsx index f1c71f78b7..bd101266a0 100644 --- a/packages/routers/src/__tests__/StackRouter.test.tsx +++ b/packages/routers/src/__tests__/StackRouter.test.tsx @@ -3,10 +3,11 @@ import { CommonActions, StackRouter, StackActions } from '..'; jest.mock('nanoid/non-secure', () => ({ nanoid: () => 'test' })); it('gets initial state from route names and params with initialRouteName', () => { - const router = StackRouter({ initialRouteName: 'baz' }); + const router = StackRouter(); expect( router.getInitialState({ + initialRouteName: 'baz', routeNames: ['bar', 'baz', 'qux'], routeParamList: { baz: { answer: 42 }, @@ -24,7 +25,7 @@ it('gets initial state from route names and params with initialRouteName', () => }); it('gets initial state from route names and params without initialRouteName', () => { - const router = StackRouter({}); + const router = StackRouter(); expect( router.getInitialState({ @@ -45,7 +46,7 @@ it('gets initial state from route names and params without initialRouteName', () }); it('gets rehydrated state from partial state', () => { - const router = StackRouter({}); + const router = StackRouter(); const options = { routeNames: ['bar', 'baz', 'qux'], @@ -121,7 +122,7 @@ it('gets rehydrated state from partial state', () => { }); it("doesn't rehydrate state if it's not stale", () => { - const router = StackRouter({}); + const router = StackRouter(); const state = { index: 0, @@ -141,7 +142,7 @@ it("doesn't rehydrate state if it's not stale", () => { }); it('gets state on route names change', () => { - const router = StackRouter({}); + const router = StackRouter(); expect( router.getStateForRouteNamesChange( @@ -208,7 +209,7 @@ it('gets state on route names change', () => { }); it('gets state on route names change with initialRouteName', () => { - const router = StackRouter({ initialRouteName: 'qux' }); + const router = StackRouter(); expect( router.getStateForRouteNamesChange( @@ -224,6 +225,7 @@ it('gets state on route names change with initialRouteName', () => { type: 'stack', }, { + initialRouteName: 'qux', routeNames: ['baz', 'qux'], routeParamList: { baz: { name: 'John' }, @@ -241,7 +243,7 @@ it('gets state on route names change with initialRouteName', () => { }); it('handles navigate action', () => { - const router = StackRouter({}); + const router = StackRouter(); const options = { routeNames: ['baz', 'bar', 'qux'], routeParamList: {}, @@ -428,7 +430,7 @@ it('handles navigate action', () => { }); it('handles go back action', () => { - const router = StackRouter({}); + const router = StackRouter(); const options = { routeNames: ['baz', 'bar', 'qux'], routeParamList: {}, @@ -476,7 +478,7 @@ it('handles go back action', () => { }); it('handles pop action', () => { - const router = StackRouter({}); + const router = StackRouter(); const options = { routeNames: ['baz', 'bar', 'qux'], routeParamList: {}, @@ -649,7 +651,7 @@ it('handles pop action', () => { }); it('handles pop to top action', () => { - const router = StackRouter({}); + const router = StackRouter(); const options = { routeNames: ['baz', 'bar', 'qux'], routeParamList: {}, @@ -683,7 +685,7 @@ it('handles pop to top action', () => { }); it('replaces focused screen with replace', () => { - const router = StackRouter({}); + const router = StackRouter(); const options = { routeNames: ['foo', 'bar', 'baz', 'qux'], routeParamList: {}, @@ -721,7 +723,7 @@ it('replaces focused screen with replace', () => { }); it('replaces active screen with replace', () => { - const router = StackRouter({}); + const router = StackRouter(); const options = { routeNames: ['foo', 'bar', 'baz', 'qux'], routeParamList: {}, @@ -762,7 +764,7 @@ it('replaces active screen with replace', () => { }); it("doesn't handle replace if source key isn't present", () => { - const router = StackRouter({}); + const router = StackRouter(); const options = { routeNames: ['foo', 'bar', 'baz', 'qux'], routeParamList: {}, @@ -793,7 +795,7 @@ it("doesn't handle replace if source key isn't present", () => { }); it("doesn't handle replace if screen to replace with isn't present", () => { - const router = StackRouter({}); + const router = StackRouter(); const options = { routeNames: ['foo', 'bar', 'baz', 'qux'], routeParamList: {}, @@ -823,7 +825,7 @@ it("doesn't handle replace if screen to replace with isn't present", () => { }); it('handles push action', () => { - const router = StackRouter({}); + const router = StackRouter(); const options = { routeNames: ['baz', 'bar', 'qux'], routeParamList: { @@ -898,7 +900,7 @@ it('handles push action', () => { }); it('changes index on focus change', () => { - const router = StackRouter({}); + const router = StackRouter(); expect( router.getStateForRouteFocus( diff --git a/packages/routers/src/__tests__/TabRouter.test.tsx b/packages/routers/src/__tests__/TabRouter.test.tsx index e6fb2f5843..1cebfc4e6c 100644 --- a/packages/routers/src/__tests__/TabRouter.test.tsx +++ b/packages/routers/src/__tests__/TabRouter.test.tsx @@ -7,6 +7,7 @@ it('gets initial state from route names and params with initialRouteName', () => expect( router.getInitialState({ + initialRouteName: 'baz', routeNames: ['bar', 'baz', 'qux'], routeParamList: { baz: { answer: 42 }, @@ -29,7 +30,7 @@ it('gets initial state from route names and params with initialRouteName', () => }); it('gets initial state from route names and params without initialRouteName', () => { - const router = TabRouter({}); + const router = TabRouter(); expect( router.getInitialState({ @@ -55,7 +56,7 @@ it('gets initial state from route names and params without initialRouteName', () }); it('gets rehydrated state from partial state', () => { - const router = TabRouter({}); + const router = TabRouter(); const options = { routeNames: ['bar', 'baz', 'qux'], @@ -190,7 +191,7 @@ it('gets rehydrated state from partial state', () => { }); it("doesn't rehydrate state if it's not stale", () => { - const router = TabRouter({}); + const router = TabRouter(); const state: TabNavigationState = { index: 0, @@ -370,7 +371,7 @@ it('restores correct history on rehydrating with backBehavior: none', () => { }); it('gets state on route names change', () => { - const router = TabRouter({}); + const router = TabRouter(); expect( router.getStateForRouteNamesChange( @@ -444,7 +445,7 @@ it('gets state on route names change', () => { }); it('preserves focused route on route names change', () => { - const router = TabRouter({}); + const router = TabRouter(); expect( router.getStateForRouteNamesChange( @@ -485,8 +486,50 @@ it('preserves focused route on route names change', () => { }); }); +it('falls back to initial route if route is removed on route names change and initialRouteName is given', () => { + const router = TabRouter({ initialRouteName: 'bar' }); + + expect( + router.getStateForRouteNamesChange( + { + index: 1, + key: 'tab-test', + routeNames: ['bar', 'baz', 'qux'], + routes: [ + { key: 'bar-test', name: 'bar' }, + { key: 'baz-test', name: 'baz', params: { answer: 42 } }, + { key: 'qux-test', name: 'qux', params: { name: 'Jane' } }, + ], + history: [{ type: 'route', key: 'baz-test' }], + stale: false, + type: 'tab', + }, + { + initialRouteName: 'fiz', + routeNames: ['qux', 'foo', 'fiz'], + routeParamList: { + qux: { name: 'John' }, + fiz: { fruit: 'apple' }, + }, + } + ) + ).toEqual({ + index: 2, + key: 'tab-test', + routeNames: ['qux', 'foo', 'fiz'], + routes: [ + { key: 'qux-test', name: 'qux', params: { name: 'Jane' } }, + { key: 'foo-test', name: 'foo', params: undefined }, + { key: 'fiz-test', name: 'fiz', params: { fruit: 'apple' } }, + ], + history: [{ type: 'route', key: 'fiz-test' }], + stale: false, + type: 'tab', + }); +}); + it('falls back to first route if route is removed on route names change', () => { - const router = TabRouter({}); + const router = TabRouter(); expect( router.getStateForRouteNamesChange( @@ -527,7 +570,7 @@ it('falls back to first route if route is removed on route names change', () => }); it('handles navigate action', () => { - const router = TabRouter({}); + const router = TabRouter(); const options = { routeNames: ['bar', 'baz'], routeParamList: {}, @@ -617,7 +660,7 @@ it('handles navigate action', () => { }); it('handles jump to action', () => { - const router = TabRouter({}); + const router = TabRouter(); const options = { routeNames: ['bar', 'baz'], routeParamList: {}, @@ -889,6 +932,7 @@ it('handles back action with backBehavior: initialRoute and initialRouteName', ( }); const options = { + initialRouteName: 'baz', routeNames: ['bar', 'baz', 'qux'], routeParamList: {}, }; diff --git a/packages/routers/src/types.tsx b/packages/routers/src/types.tsx index 60179f542f..0c79130dc7 100644 --- a/packages/routers/src/types.tsx +++ b/packages/routers/src/types.tsx @@ -109,6 +109,7 @@ export type RouterFactory< > = (options: RouterOptions) => Router; export type RouterConfigOptions = { + initialRouteName?: string; routeNames: string[]; routeParamList: ParamListBase; };