fix: handle pushing a route with duplicate key

Currently, stack router adds a duplicate route when pushing a new route with a key that already exists. This is a buggy behaviour since keys need to be unique in the stack.

This commit fixes the behaviour to bring the existing route with the same key to focus (and merge new params if any) instead of adding a duplicate route.
This commit is contained in:
Satyajit Sahoo
2020-10-08 19:58:36 +02:00
parent 01f86d2ac6
commit 091b2a2038
2 changed files with 105 additions and 7 deletions

View File

@@ -256,10 +256,35 @@ export default function StackRouter(options: StackRouterOptions) {
case 'PUSH':
if (state.routeNames.includes(action.payload.name)) {
return {
...state,
index: state.index + 1,
routes: [
const route =
action.payload.name && action.payload.key
? state.routes.find(
(route) =>
route.name === action.payload.name &&
route.key === action.payload.key
)
: undefined;
let routes: Route<string>[];
if (route) {
routes = state.routes.filter((r) => r.key !== route.key);
routes.push(
action.payload.params
? {
...route,
params:
action.payload.params !== undefined
? {
...route.params,
...action.payload.params,
}
: route.params,
}
: route
);
} else {
routes = [
...state.routes,
{
key:
@@ -275,7 +300,13 @@ export default function StackRouter(options: StackRouterOptions) {
}
: action.payload.params,
},
],
];
}
return {
...state,
index: routes.length - 1,
routes,
};
}

View File

@@ -848,7 +848,7 @@ it('handles push action', () => {
stale: false,
type: 'stack',
key: 'root',
index: 3,
index: 1,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'bar', name: 'bar' },
@@ -873,7 +873,7 @@ it('handles push action', () => {
stale: false,
type: 'stack',
key: 'root',
index: 3,
index: 1,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'bar', name: 'bar' },
@@ -895,6 +895,73 @@ it('handles push action', () => {
options
)
).toBe(null);
expect(
router.getStateForAction(
{
stale: false,
type: 'stack',
key: 'root',
index: 2,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'bar-3', name: 'bar' },
{ key: 'bar-4', name: 'bar', params: { foo: 21 } },
{ key: 'baz-5', name: 'baz' },
],
},
{
type: 'PUSH',
payload: { name: 'bar', key: 'bar-4', params: { bar: 29 } },
},
options
)
).toEqual({
stale: false,
type: 'stack',
key: 'root',
index: 2,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'bar-3', name: 'bar' },
{ key: 'baz-5', name: 'baz' },
{ key: 'bar-4', name: 'bar', params: { foo: 21, bar: 29 } },
],
});
expect(
router.getStateForAction(
{
stale: false,
type: 'stack',
key: 'root',
index: 2,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'bar-3', name: 'bar' },
{ key: 'bar-4', name: 'bar' },
{ key: 'baz-5', name: 'baz' },
],
},
{
type: 'PUSH',
payload: { name: 'bar', key: 'bar-6', params: { bar: 29 } },
},
options
)
).toEqual({
stale: false,
type: 'stack',
key: 'root',
index: 3,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'bar-3', name: 'bar' },
{ key: 'bar-4', name: 'bar' },
{ key: 'baz-5', name: 'baz' },
{ key: 'bar-6', name: 'bar', params: { bar: 29 } },
],
});
});
it('changes index on focus change', () => {