mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-04-29 12:55:21 +08:00
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:
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
Reference in New Issue
Block a user