From 531dc30530d133fe37086e9ef8804da8cf1db0ae Mon Sep 17 00:00:00 2001 From: Harry Yu Date: Mon, 18 Nov 2019 04:00:10 -0800 Subject: [PATCH] fix: don't pop routeKeyHistory when child handles back action (#75) ## Motivation When pressing back in a StackNavigator nested inside the SwitchRouter, the screen would get popped, but the routeKeyHistory of the SwitchRouter gets popped even though the SwitchRouter doesn't handle the back action. This results in the next back action skipping the last opened tab. ## Fix Before popping the `routeKeyHistory` stack, we check that the history actually changed. I also added a test for this --- packages/core/src/routers/SwitchRouter.js | 6 ++--- .../routers/__tests__/SwitchRouter-test.js | 22 +++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/packages/core/src/routers/SwitchRouter.js b/packages/core/src/routers/SwitchRouter.js index 45ff288c..a0c406b7 100644 --- a/packages/core/src/routers/SwitchRouter.js +++ b/packages/core/src/routers/SwitchRouter.js @@ -81,8 +81,8 @@ export default (routeConfigs, config = {}) => { } function getNextState(action, prevState, possibleNextState) { - function updateNextStateHistory(nextState) { - if (backBehavior !== 'history') { + function updateNextStateHistory(prevState, nextState) { + if (backBehavior !== 'history' || nextState.index === prevState.index) { return nextState; } let nextRouteKeyHistory = prevState ? prevState.routeKeyHistory : []; @@ -115,7 +115,7 @@ export default (routeConfigs, config = {}) => { routes: nextRoutes, }; } - return updateNextStateHistory(nextState); + return updateNextStateHistory(prevState, nextState); } function getInitialState() { diff --git a/packages/core/src/routers/__tests__/SwitchRouter-test.js b/packages/core/src/routers/__tests__/SwitchRouter-test.js index 6b616d5d..5b0606bf 100644 --- a/packages/core/src/routers/__tests__/SwitchRouter-test.js +++ b/packages/core/src/routers/__tests__/SwitchRouter-test.js @@ -117,6 +117,28 @@ describe('SwitchRouter', () => { expect(getState().routeKeyHistory).toEqual(['B']); }); + it('handles history backBehavior without popping routeKeyHistory when child handles action', () => { + const { navigateTo, back, getState, getSubState } = getRouterTestHelper( + getExampleRouter({ backBehavior: 'history' }) + ); + expect(getState().routeKeyHistory).toEqual(['A']); + + navigateTo('B'); + expect(getState().index).toEqual(1); + expect(getState().routeKeyHistory).toEqual(['A', 'B']); + + navigateTo('B2'); + expect(getState().index).toEqual(1); + expect(getState().routeKeyHistory).toEqual(['A', 'B']); + expect(getSubState(2).routeName).toEqual('B2'); + + back(); + expect(getState().index).toEqual(1); + // 'B' should not be popped when the child handles the back action + expect(getState().routeKeyHistory).toEqual(['A', 'B']); + expect(getSubState(2).routeName).toEqual('B1'); + }); + it('handles nested actions', () => { const { navigateTo, getSubState } = getRouterTestHelper(getExampleRouter());