feat: add a merge option to navigate to control merging params

This commit is contained in:
Satyajit Sahoo
2020-11-04 21:40:57 +01:00
parent ec7b02af2c
commit 9beca3a802
5 changed files with 302 additions and 20 deletions

View File

@@ -16,8 +16,8 @@ export type Action =
| {
type: 'NAVIGATE';
payload:
| { key: string; name?: undefined; params?: object }
| { name: string; key?: string; params?: object };
| { key: string; name?: undefined; params?: object; merge?: boolean }
| { name: string; key?: string; params?: object; merge?: boolean };
source?: string;
target?: string;
}

View File

@@ -397,19 +397,34 @@ export default function StackRouter(options: StackRouterOptions) {
);
}
const route = state.routes[index];
let params;
if (action.payload.merge === false) {
params =
routeParamList[route.name] !== undefined
? {
...routeParamList[route.name],
...action.payload.params,
}
: action.payload.params;
} else {
params = action.payload.params
? {
...route.params,
...action.payload.params,
}
: route.params;
}
return {
...state,
index,
routes: [
...state.routes.slice(0, index),
action.payload.params !== undefined
? {
...state.routes[index],
params: {
...state.routes[index].params,
...action.payload.params,
},
}
params !== route.params
? { ...route, params }
: state.routes[index],
],
};

View File

@@ -271,7 +271,7 @@ export default function TabRouter({
return changeIndex(state, index, backBehavior, initialRouteName);
},
getStateForAction(state, action) {
getStateForAction(state, action, { routeParamList }) {
switch (action.type) {
case 'JUMP_TO':
case 'NAVIGATE': {
@@ -296,17 +296,37 @@ export default function TabRouter({
...state,
routes:
action.payload.params !== undefined
? state.routes.map((route, i) =>
i === index
? {
...route,
params: {
? state.routes.map((route, i) => {
if (i !== index) {
return route;
}
let params;
if (
action.type === 'NAVIGATE' &&
action.payload.merge === false
) {
params =
routeParamList[route.name] !== undefined
? {
...routeParamList[route.name],
...action.payload.params,
}
: action.payload.params;
} else {
params = action.payload.params
? {
...route.params,
...action.payload.params,
},
}
: route
)
}
: route.params;
}
return params !== route.params
? { ...route, params }
: route;
})
: state.routes,
},
index,

View File

@@ -1074,3 +1074,115 @@ it('merges params on navigate to an existing screen', () => {
],
});
});
it("doesn't merge params on navigate to an existing screen if merge: false", () => {
const router = StackRouter({});
const options = {
routeNames: ['baz', 'bar', 'qux'],
routeParamList: {
baz: { foo: 12 },
},
};
expect(
router.getStateForAction(
{
stale: false,
type: 'stack',
key: 'root',
index: 2,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'baz', name: 'baz' },
{ key: 'bar', name: 'bar', params: { answer: 42 } },
{ key: 'qux', name: 'qux' },
],
},
{
type: 'NAVIGATE',
payload: {
name: 'bar',
merge: false,
},
},
options
)
).toEqual({
stale: false,
type: 'stack',
key: 'root',
index: 1,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'baz', name: 'baz' },
{ key: 'bar', name: 'bar' },
],
});
expect(
router.getStateForAction(
{
stale: false,
type: 'stack',
key: 'root',
index: 1,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'baz', name: 'baz' },
{ key: 'bar', name: 'bar', params: { answer: 42 } },
],
},
{
type: 'NAVIGATE',
payload: {
name: 'bar',
params: { fruit: 'orange' },
merge: false,
},
},
options
)
).toEqual({
stale: false,
type: 'stack',
key: 'root',
index: 1,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'baz', name: 'baz' },
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
],
});
expect(
router.getStateForAction(
{
stale: false,
type: 'stack',
key: 'root',
index: 1,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'baz', name: 'baz', params: { test: 99 } },
{ key: 'bar', name: 'bar', params: { answer: 42 } },
],
},
{
type: 'NAVIGATE',
payload: {
name: 'baz',
params: { color: 'black' },
merge: false,
},
},
options
)
).toEqual({
stale: false,
type: 'stack',
key: 'root',
index: 0,
routeNames: ['baz', 'bar', 'qux'],
routes: [{ key: 'baz', name: 'baz', params: { foo: 12, color: 'black' } }],
});
});

View File

@@ -1186,6 +1186,141 @@ it('merges params on navigate to an existing screen', () => {
});
});
it("doesn't merge params on navigate to an existing screen if merge: false", () => {
const router = TabRouter({});
const options = {
routeNames: ['baz', 'bar', 'qux'],
routeParamList: {
qux: { color: 'indigo' },
},
};
expect(
router.getStateForAction(
{
stale: false,
type: 'tab',
key: 'root',
index: 1,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'baz', name: 'baz' },
{ key: 'bar', name: 'bar', params: { answer: 42 } },
{ key: 'qux', name: 'qux' },
],
history: [{ type: 'route', key: 'baz' }],
},
{
type: 'NAVIGATE',
payload: {
name: 'bar',
merge: false,
},
},
options
)
).toEqual({
stale: false,
type: 'tab',
key: 'root',
index: 1,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'baz', name: 'baz' },
{ key: 'bar', name: 'bar', params: { answer: 42 } },
{ key: 'qux', name: 'qux' },
],
history: [
{ type: 'route', key: 'baz' },
{ type: 'route', key: 'bar' },
],
});
expect(
router.getStateForAction(
{
stale: false,
type: 'tab',
key: 'root',
index: 1,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'baz', name: 'baz' },
{ key: 'bar', name: 'bar' },
{ key: 'qux', name: 'qux' },
],
history: [{ type: 'route', key: 'baz' }],
},
{
type: 'NAVIGATE',
payload: {
name: 'bar',
params: { fruit: 'orange' },
merge: false,
},
},
options
)
).toEqual({
stale: false,
type: 'tab',
key: 'root',
index: 1,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'baz', name: 'baz' },
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
{ key: 'qux', name: 'qux' },
],
history: [
{ type: 'route', key: 'baz' },
{ type: 'route', key: 'bar' },
],
});
expect(
router.getStateForAction(
{
stale: false,
type: 'tab',
key: 'root',
index: 1,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'baz', name: 'baz' },
{ key: 'bar', name: 'bar' },
{ key: 'qux', name: 'qux' },
],
history: [{ type: 'route', key: 'baz' }],
},
{
type: 'NAVIGATE',
payload: {
name: 'qux',
params: { test: 12 },
merge: false,
},
},
options
)
).toEqual({
stale: false,
type: 'tab',
key: 'root',
index: 2,
routeNames: ['baz', 'bar', 'qux'],
routes: [
{ key: 'baz', name: 'baz' },
{ key: 'bar', name: 'bar' },
{ key: 'qux', name: 'qux', params: { color: 'indigo', test: 12 } },
],
history: [
{ type: 'route', key: 'baz' },
{ type: 'route', key: 'qux' },
],
});
});
it('merges params on jump to an existing screen', () => {
const router = TabRouter({});
const options = {