mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-06 22:39:41 +08:00
feat: add a merge option to navigate to control merging params
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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],
|
||||
],
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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' } }],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user