StackRouter PopN Action (#3404)

This commit is contained in:
Eric Vicenti
2018-02-01 17:01:04 -08:00
parent 35f7961a8d
commit d93092e91a
6 changed files with 68 additions and 4 deletions

View File

@@ -1,6 +1,7 @@
const BACK = 'Navigation/BACK';
const INIT = 'Navigation/INIT';
const NAVIGATE = 'Navigation/NAVIGATE';
const POP = 'Navigation/POP';
const RESET = 'Navigation/RESET';
const SET_PARAMS = 'Navigation/SET_PARAMS';
const URI = 'Navigation/URI';
@@ -43,6 +44,12 @@ const navigate = createAction(NAVIGATE, payload => {
return action;
});
const pop = createAction(POP, payload => ({
type: POP,
n: payload && payload.n,
immediate: payload && payload.immediate,
}));
const reset = createAction(RESET, payload => ({
type: RESET,
index: payload.index,
@@ -123,6 +130,7 @@ export default {
BACK,
INIT,
NAVIGATE,
POP,
RESET,
SET_PARAMS,
URI,
@@ -132,6 +140,7 @@ export default {
back,
init,
navigate,
pop,
reset,
setParams,
uri,

View File

@@ -39,6 +39,10 @@ export default function(navigation) {
);
return navigation.dispatch(NavigationActions.navigate(navigateTo));
},
pop: (n, params) =>
navigation.dispatch(
NavigationActions.pop({ n, immediate: params && params.immediate })
),
/**
* For updating current route params. For example the nav bar title and
* buttons are based on the route params.

View File

@@ -97,6 +97,7 @@ exports[`StackNavigator applies correct values when headerRight is present 1`] =
"dispatch": [Function],
"goBack": [Function],
"navigate": [Function],
"pop": [Function],
"setParams": [Function],
"state": Object {
"index": 0,
@@ -330,6 +331,7 @@ exports[`StackNavigator renders successfully 1`] = `
"dispatch": [Function],
"goBack": [Function],
"navigate": [Function],
"pop": [Function],
"setParams": [Function],
"state": Object {
"index": 0,

View File

@@ -326,10 +326,17 @@ export default (routeConfigs, stackConfig = {}) => {
};
}
if (action.type === NavigationActions.BACK) {
const key = action.key;
if (
action.type === NavigationActions.BACK ||
action.type === NavigationActions.POP
) {
const { key, n, immediate } = action;
let backRouteIndex = state.index;
if (key) {
if (action.type === NavigationActions.POP && n != null) {
// determine the index to go back *from*. In this case, n=1 means to go
// back from state.index, as if it were a normal "BACK" action
backRouteIndex = Math.max(1, state.index - n + 1);
} else if (key) {
const backRoute = state.routes.find(route => route.key === key);
backRouteIndex = state.routes.indexOf(backRoute);
}
@@ -338,7 +345,7 @@ export default (routeConfigs, stackConfig = {}) => {
...state,
routes: state.routes.slice(0, backRouteIndex),
index: backRouteIndex - 1,
isTransitioning: action.immediate !== true,
isTransitioning: immediate !== true,
};
}
}

View File

@@ -713,6 +713,47 @@ describe('TabRouter', () => {
expect(state2).toEqual(state0);
});
test('pop action works as expected', () => {
const TestRouter = StackRouter({
foo: { screen: () => <div /> },
bar: { screen: () => <div /> },
});
const state = {
index: 3,
isTransitioning: false,
routes: [
{ key: 'A', routeName: 'foo' },
{ key: 'B', routeName: 'bar', params: { bazId: '321' } },
{ key: 'C', routeName: 'foo' },
{ key: 'D', routeName: 'bar' },
],
};
const poppedState = TestRouter.getStateForAction(
NavigationActions.pop(),
state
);
expect(poppedState.routes.length).toBe(3);
expect(poppedState.index).toBe(2);
expect(poppedState.isTransitioning).toBe(true);
const poppedState2 = TestRouter.getStateForAction(
NavigationActions.pop({ n: 2, immediate: true }),
state
);
expect(poppedState2.routes.length).toBe(2);
expect(poppedState2.index).toBe(1);
expect(poppedState2.isTransitioning).toBe(false);
const poppedState3 = TestRouter.getStateForAction(
NavigationActions.pop({ n: 5 }),
state
);
expect(poppedState3.routes.length).toBe(1);
expect(poppedState3.index).toBe(0);
expect(poppedState3.isTransitioning).toBe(true);
});
test('Inner actions are only unpacked if the current tab matches', () => {
const PlainScreen = () => <div />;
const ScreenA = () => <div />;

View File

@@ -224,6 +224,7 @@ exports[`TabBarBottom renders successfully 1`] = `
"dispatch": undefined,
"goBack": [Function],
"navigate": [Function],
"pop": [Function],
"setParams": [Function],
"state": Object {
"key": "s1",