refactor: discard all routes but last when getting action from state

This commit is contained in:
Satyajit Sahoo
2020-02-14 23:04:09 +01:00
parent c5fcfbd427
commit ac242fd281
5 changed files with 86 additions and 69 deletions

View File

@@ -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: '' }
),
},
},

View File

@@ -41,10 +41,9 @@ it('gets navigate action from state', () => {
},
type: 'NAVIGATE',
});
});
it('gets reset action from state', () => {
const state = {
expect(
getActionFromState({
routes: [
{
name: 'foo',
@@ -66,10 +65,40 @@ it('gets reset action from state', () => {
},
},
],
};
expect(getActionFromState(state)).toEqual({
payload: state,
type: 'RESET_ROOT',
})
).toEqual({
payload: {
name: 'foo',
params: {
screen: 'bar',
params: {
screen: 'quz',
},
},
},
type: 'NAVIGATE',
});
});
it('gets reset action from state', () => {
const state = {
routes: [
{
name: 'foo',
state: {
routes: [
{
name: 'bar',
state: {
routes: [],
},
},
],
},
},
],
};
expect(getActionFromState(state)).toBe(undefined);
expect(getActionFromState({ routes: [] })).toBe(undefined);
});

View File

@@ -5,37 +5,36 @@ type NavigateParams = {
params?: NavigateParams;
};
type Action =
| {
type NavigateAction = {
type: 'NAVIGATE';
payload: { name: string; params: NavigateParams };
}
| {
type: 'RESET_ROOT';
payload: PartialState<NavigationState>;
};
};
export default function getActionFromState(
state: PartialState<NavigationState>
): Action {
let payload: { name: string; params: NavigateParams } | undefined;
): NavigateAction | undefined {
if (state.routes.length === 0) {
return 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];
let route = state.routes[state.routes.length - 1];
payload = {
let payload: { name: string; params: NavigateParams } = {
name: route.name,
params: { ...route.params },
};
let current = state.routes[0].state;
let current = route.state;
let params = payload.params;
while (current) {
if (current.routes.length === 1) {
route = current.routes[0];
if (current.routes.length === 0) {
return undefined;
}
route = current.routes[current.routes.length - 1];
params.screen = route.name;
if (route.state) {
@@ -46,22 +45,10 @@ export default function getActionFromState(
}
current = route.state;
} else {
payload = undefined;
break;
}
}
}
if (payload) {
return {
type: 'NAVIGATE',
payload,
};
}
return {
type: 'RESET_ROOT',
payload: state,
};
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}