From ac242fd28110132182d4e315b100601bf779712b Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Fri, 14 Feb 2020 23:04:09 +0100 Subject: [PATCH] refactor: discard all routes but last when getting action from state --- example/src/index.tsx | 5 +- .../src/__tests__/getActionFromState.test.tsx | 51 ++++++++--- packages/core/src/getActionFromState.tsx | 87 ++++++++----------- packages/native/src/useLinking.native.tsx | 6 +- packages/native/src/useLinking.tsx | 6 +- 5 files changed, 86 insertions(+), 69 deletions(-) diff --git a/example/src/index.tsx b/example/src/index.tsx index 2c69bb47..ad7ffc66 100644 --- a/example/src/index.tsx +++ b/example/src/index.tsx @@ -124,7 +124,8 @@ export default function App() { prefixes: LinkingPrefixes, config: { Root: { - path: 'root', + path: '', + initialRouteName: 'Home', screens: Object.keys(SCREENS).reduce<{ [key: string]: string }>( (acc, name) => { // Convert screen names such as SimpleStack to kebab case (simple-stack) @@ -135,7 +136,7 @@ export default function App() { return acc; }, - {} + { Home: '' } ), }, }, diff --git a/packages/core/src/__tests__/getActionFromState.test.tsx b/packages/core/src/__tests__/getActionFromState.test.tsx index a95e3448..05a82726 100644 --- a/packages/core/src/__tests__/getActionFromState.test.tsx +++ b/packages/core/src/__tests__/getActionFromState.test.tsx @@ -41,6 +41,43 @@ it('gets navigate action from state', () => { }, type: 'NAVIGATE', }); + + expect( + getActionFromState({ + routes: [ + { + name: 'foo', + state: { + routes: [ + { + name: 'bar', + state: { + routes: [ + { + name: 'qux', + params: { author: 'jane' }, + }, + { name: 'quz' }, + ], + }, + }, + ], + }, + }, + ], + }) + ).toEqual({ + payload: { + name: 'foo', + params: { + screen: 'bar', + params: { + screen: 'quz', + }, + }, + }, + type: 'NAVIGATE', + }); }); it('gets reset action from state', () => { @@ -53,13 +90,7 @@ it('gets reset action from state', () => { { name: 'bar', state: { - routes: [ - { - name: 'qux', - params: { author: 'jane' }, - }, - { name: 'quz' }, - ], + routes: [], }, }, ], @@ -68,8 +99,6 @@ it('gets reset action from state', () => { ], }; - expect(getActionFromState(state)).toEqual({ - payload: state, - type: 'RESET_ROOT', - }); + expect(getActionFromState(state)).toBe(undefined); + expect(getActionFromState({ routes: [] })).toBe(undefined); }); diff --git a/packages/core/src/getActionFromState.tsx b/packages/core/src/getActionFromState.tsx index 1c4512b4..a3aed6fd 100644 --- a/packages/core/src/getActionFromState.tsx +++ b/packages/core/src/getActionFromState.tsx @@ -5,63 +5,50 @@ type NavigateParams = { params?: NavigateParams; }; -type Action = - | { - type: 'NAVIGATE'; - payload: { name: string; params: NavigateParams }; - } - | { - type: 'RESET_ROOT'; - payload: PartialState; - }; +type NavigateAction = { + type: 'NAVIGATE'; + payload: { name: string; params: NavigateParams }; +}; export default function getActionFromState( state: PartialState -): Action { - let payload: { name: string; params: NavigateParams } | undefined; - - if (state.routes.length === 1) { - // Try to construct payload for a `NAVIGATE` action from the state - // This lets us preserve the navigation state and not lose it - let route = state.routes[0]; - - payload = { - name: route.name, - params: { ...route.params }, - }; - - let current = state.routes[0].state; - let params = payload.params; - - while (current) { - if (current.routes.length === 1) { - route = current.routes[0]; - params.screen = route.name; - - if (route.state) { - params.params = { ...route.params }; - params = params.params; - } else { - params.params = route.params; - } - - current = route.state; - } else { - payload = undefined; - break; - } - } +): NavigateAction | undefined { + if (state.routes.length === 0) { + return undefined; } - if (payload) { - return { - type: 'NAVIGATE', - payload, - }; + // Try to construct payload for a `NAVIGATE` action from the state + // This lets us preserve the navigation state and not lose it + let route = state.routes[state.routes.length - 1]; + + let payload: { name: string; params: NavigateParams } = { + name: route.name, + params: { ...route.params }, + }; + + let current = route.state; + let params = payload.params; + + while (current) { + if (current.routes.length === 0) { + return undefined; + } + + route = current.routes[current.routes.length - 1]; + params.screen = route.name; + + if (route.state) { + params.params = { ...route.params }; + params = params.params; + } else { + params.params = route.params; + } + + current = route.state; } return { - type: 'RESET_ROOT', - payload: state, + type: 'NAVIGATE', + payload, }; } diff --git a/packages/native/src/useLinking.native.tsx b/packages/native/src/useLinking.native.tsx index f694e32e..1d1e2525 100644 --- a/packages/native/src/useLinking.native.tsx +++ b/packages/native/src/useLinking.native.tsx @@ -76,10 +76,10 @@ export default function useLinking( if (state) { const action = getActionFromState(state); - if (action.type === 'RESET_ROOT') { - navigation.resetRoot(action.payload); - } else { + if (action !== undefined) { navigation.dispatch(action); + } else { + navigation.resetRoot(state); } } } diff --git a/packages/native/src/useLinking.tsx b/packages/native/src/useLinking.tsx index 0522dc13..0d6cee14 100644 --- a/packages/native/src/useLinking.tsx +++ b/packages/native/src/useLinking.tsx @@ -162,10 +162,10 @@ export default function useLinking( pendingStateUpdateRef.current = true; - if (action.type === 'RESET_ROOT') { - navigation.resetRoot(action.payload); - } else { + if (action !== undefined) { navigation.dispatch(action); + } else { + navigation.resetRoot(state); } } }