New StackRouter Push Action (#3401)

This commit is contained in:
Eric Vicenti
2018-02-01 17:14:13 -08:00
parent 7f3238d3db
commit 83ee866e29
6 changed files with 60 additions and 4 deletions

View File

@@ -3,6 +3,7 @@ const INIT = 'Navigation/INIT';
const NAVIGATE = 'Navigation/NAVIGATE';
const POP = 'Navigation/POP';
const POP_TO_TOP = 'Navigation/POP_TO_TOP';
const PUSH = 'Navigation/PUSH';
const RESET = 'Navigation/RESET';
const SET_PARAMS = 'Navigation/SET_PARAMS';
const URI = 'Navigation/URI';
@@ -56,6 +57,20 @@ const popToTop = createAction(POP_TO_TOP, payload => ({
immediate: payload && payload.immediate,
}));
const push = createAction(PUSH, payload => {
const action = {
type: PUSH,
routeName: payload.routeName,
};
if (payload.params) {
action.params = payload.params;
}
if (payload.action) {
action.action = payload.action;
}
return action;
});
const reset = createAction(RESET, payload => ({
type: RESET,
index: payload.index,
@@ -138,6 +153,7 @@ export default {
NAVIGATE,
POP,
POP_TO_TOP,
PUSH,
RESET,
SET_PARAMS,
URI,
@@ -149,6 +165,7 @@ export default {
navigate,
pop,
popToTop,
push,
reset,
setParams,
uri,

View File

@@ -60,5 +60,10 @@ export default function(navigation) {
const key = navigation.state.key;
return navigation.dispatch(NavigationActions.setParams({ params, key }));
},
push: (routeName, params, action) =>
navigation.dispatch(
NavigationActions.push({ routeName, params, action })
),
};
}

View File

@@ -99,6 +99,7 @@ exports[`StackNavigator applies correct values when headerRight is present 1`] =
"navigate": [Function],
"pop": [Function],
"popToTop": [Function],
"push": [Function],
"setParams": [Function],
"state": Object {
"index": 0,
@@ -334,6 +335,7 @@ exports[`StackNavigator renders successfully 1`] = `
"navigate": [Function],
"pop": [Function],
"popToTop": [Function],
"push": [Function],
"setParams": [Function],
"state": Object {
"index": 0,

View File

@@ -17,6 +17,13 @@ function isEmpty(obj) {
return true;
}
function behavesLikePushAction(action) {
return (
action.type === NavigationActions.NAVIGATE ||
action.type === NavigationActions.PUSH
);
}
export default (routeConfigs, stackConfig = {}) => {
// Fail fast on invalid route definitions
validateRouteConfigMap(routeConfigs);
@@ -96,7 +103,7 @@ export default (routeConfigs, stackConfig = {}) => {
if (!state) {
let route = {};
if (
action.type === NavigationActions.NAVIGATE &&
behavesLikePushAction(action) &&
childRouters[action.routeName] !== undefined
) {
return {
@@ -178,13 +185,17 @@ export default (routeConfigs, stackConfig = {}) => {
// Handle explicit push navigation action. Make sure this happens after children have had a chance to handle the action
if (
action.type === NavigationActions.NAVIGATE &&
behavesLikePushAction(action) &&
childRouters[action.routeName] !== undefined
) {
const childRouter = childRouters[action.routeName];
let route;
// The key may be provided for pushing, or to navigate back to the key
invariant(
action.type !== NavigationActions.PUSH || action.key == null,
'StackRouter does not support key on the push action'
);
// With the navigate action, the key may be provided for pushing, or to navigate back to the key
if (action.key) {
const lastRouteIndex = state.routes.findIndex(
r => r.key === action.key
@@ -252,7 +263,7 @@ export default (routeConfigs, stackConfig = {}) => {
}
// Handle navigation to other child routers that are not yet pushed
if (action.type === NavigationActions.NAVIGATE) {
if (behavesLikePushAction(action)) {
const childRouterNames = Object.keys(childRouters);
for (let i = 0; i < childRouterNames.length; i++) {
const childRouterName = childRouterNames[i];

View File

@@ -441,6 +441,26 @@ describe('StackRouter', () => {
expect(pushedTwiceState.routes[1].routeName).toEqual('bar');
});
test('Push behaves like navigate, except for key', () => {
const TestRouter = StackRouter({
foo: { screen: () => <div /> },
bar: { screen: () => <div /> },
});
const initState = TestRouter.getStateForAction(NavigationActions.init());
const pushedState = TestRouter.getStateForAction(
NavigationActions.push({ routeName: 'bar' }),
initState
);
expect(pushedState.index).toEqual(1);
expect(pushedState.routes[1].routeName).toEqual('bar');
expect(() => {
TestRouter.getStateForAction(
{ type: NavigationActions.PUSH, routeName: 'bar', key: 'a' },
pushedState
);
}).toThrow();
});
test('Handle basic stack logic for plain components', () => {
const FooScreen = () => <div />;
const BarScreen = () => <div />;

View File

@@ -226,6 +226,7 @@ exports[`TabBarBottom renders successfully 1`] = `
"navigate": [Function],
"pop": [Function],
"popToTop": [Function],
"push": [Function],
"setParams": [Function],
"state": Object {
"key": "s1",