refactor: move replace to stack router

This commit is contained in:
Satyajit Sahoo
2020-01-23 20:13:40 +01:00
parent 16c64e7298
commit 9976a888a0
6 changed files with 178 additions and 99 deletions

View File

@@ -683,6 +683,145 @@ it('handles pop to top action', () => {
});
});
it('replaces focused screen with replace', () => {
const router = StackRouter({});
const options = {
routeNames: ['foo', 'bar', 'baz', 'qux'],
routeParamList: {},
};
expect(
router.getStateForAction(
{
stale: false,
type: 'stack',
key: 'root',
index: 1,
routes: [
{ key: 'foo', name: 'foo' },
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
{ key: 'baz', name: 'baz' },
],
routeNames: ['foo', 'bar', 'baz', 'qux'],
},
StackActions.replace('qux', { answer: 42 }),
options
)
).toEqual({
stale: false,
type: 'stack',
key: 'root',
index: 1,
routes: [
{ key: 'foo', name: 'foo' },
{ key: 'qux-test', name: 'qux', params: { answer: 42 } },
{ key: 'baz', name: 'baz' },
],
routeNames: ['foo', 'bar', 'baz', 'qux'],
});
});
it('replaces source screen with replace', () => {
const router = StackRouter({});
const options = {
routeNames: ['foo', 'bar', 'baz', 'qux'],
routeParamList: {},
};
expect(
router.getStateForAction(
{
stale: false,
type: 'stack',
key: 'root',
index: 1,
routes: [
{ key: 'foo', name: 'foo' },
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
{ key: 'baz', name: 'baz' },
],
routeNames: ['foo', 'bar', 'baz', 'qux'],
},
{
...StackActions.replace('qux', { answer: 42 }),
source: 'baz',
},
options
)
).toEqual({
stale: false,
type: 'stack',
key: 'root',
index: 1,
routes: [
{ key: 'foo', name: 'foo' },
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
{ key: 'qux-test', name: 'qux', params: { answer: 42 } },
],
routeNames: ['foo', 'bar', 'baz', 'qux'],
});
});
it("doesn't handle replace if source key isn't present", () => {
const router = StackRouter({});
const options = {
routeNames: ['foo', 'bar', 'baz', 'qux'],
routeParamList: {},
};
expect(
router.getStateForAction(
{
stale: false,
type: 'stack',
key: 'root',
index: 1,
routes: [
{ key: 'foo', name: 'foo' },
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
{ key: 'baz', name: 'baz' },
],
routeNames: ['foo', 'bar', 'baz', 'qux'],
},
{
...StackActions.replace('qux', { answer: 42 }),
source: 'magic',
},
options
)
).toBe(null);
});
it("doesn't handle replace if screen to replace with isn't present", () => {
const router = StackRouter({});
const options = {
routeNames: ['foo', 'bar', 'baz', 'qux'],
routeParamList: {},
};
expect(
router.getStateForAction(
{
stale: false,
type: 'stack',
key: 'root',
index: 1,
routes: [
{ key: 'foo', name: 'foo' },
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
{ key: 'baz', name: 'baz' },
],
routeNames: ['foo', 'bar', 'baz', 'qux'],
},
{
...StackActions.replace('nonexistent', { answer: 42 }),
source: 'magic',
},
options
)
).toBe(null);
});
it('handles push action', () => {
const router = StackRouter({});
const options = {

View File

@@ -9,6 +9,12 @@ import {
} from '@react-navigation/core';
export type StackActionType =
| {
type: 'REPLACE';
payload: { name: string; key?: string | undefined; params?: object };
source?: string;
target?: string;
}
| {
type: 'PUSH';
payload: { name: string; key?: string | undefined; params?: object };
@@ -37,6 +43,9 @@ export type StackNavigationState = NavigationState & {
};
export const StackActions = {
replace(name: string, params?: object): StackActionType {
return { type: 'REPLACE', payload: { name, params } };
},
push(name: string, params?: object): StackActionType {
return { type: 'PUSH', payload: { name, params } };
},
@@ -169,6 +178,35 @@ export default function StackRouter(options: StackRouterOptions) {
const { routeParamList } = options;
switch (action.type) {
case 'REPLACE': {
const index = action.source
? state.routes.findIndex(r => r.key === action.source)
: state.index;
if (index === -1) {
return null;
}
const { name, key, params } = action.payload;
if (!state.routeNames.includes(name)) {
return null;
}
return {
...state,
routes: state.routes.map((route, i) =>
i === index
? {
key: key !== undefined ? key : `${name}-${shortid()}`,
name,
params,
}
: route
),
};
}
case 'PUSH':
if (state.routeNames.includes(action.payload.name)) {
return {