Reset specific StackRouter with key (#789)

* First test

* Allow a key to be passed for which scene should handle the action

* Adding key to NavigationResetAction

* Added test

* Add reset test with key

* Only apply this change if it is a RESET action

* Fix logic error, only check if the action is null if it is a RESET
This commit is contained in:
Scott Brady
2017-04-04 20:26:37 -04:00
committed by Eric Vicenti
parent e8726c1e68
commit e402eba3a7
3 changed files with 40 additions and 7 deletions

View File

@@ -253,6 +253,7 @@ export type NavigationInitAction = {
export type NavigationResetAction = {
type: 'Navigation/RESET',
index: number,
key?: ?string,
actions: Array<NavigationNavigateAction>,
};

View File

@@ -130,13 +130,18 @@ export default (
};
}
// Check if the current scene wants to handle the action
const currentRoute = state.routes[state.index];
const childRouter = childRouters[currentRoute.routeName];
if (childRouter) {
const route = childRouter.getStateForAction(action, currentRoute);
if (route && route !== currentRoute) {
return StateUtils.replaceAt(state, currentRoute.key, route);
// Check if a child scene wants to handle the action as long as it is not a reset to the root stack
if(action.type !== NavigationActions.RESET || action.key !== null) {
const keyIndex = action.key ? StateUtils.indexOf(state, action.key) : -1
const childIndex = keyIndex >= 0 ? keyIndex : state.index;
const childRoute = state.routes[childIndex];
const childRouter = childRouters[childRoute.routeName];
if (childRouter) {
delete action.key;
const route = childRouter.getStateForAction(action, childRoute);
if (route && route !== childRoute) {
return StateUtils.replaceAt(state, childRoute.key, route);
}
}
}

View File

@@ -488,6 +488,33 @@ describe('StackRouter', () => {
expect(state2 && state2.routes[0].routes[0].routeName).toEqual('baz');
});
test('Handles the reset action with a key', () => {
const ChildRouter = StackRouter({
baz: {
screen: () => <div />,
},
});
const ChildNavigator = () => <div />;
ChildNavigator.router = ChildRouter;
const router = StackRouter({
Foo: {
screen: ChildNavigator,
},
Bar: {
screen: () => <div />,
},
});
const state = router.getStateForAction({ type: NavigationActions.INIT });
const state2 = router.getStateForAction({ type: NavigationActions.NAVIGATE, routeName: 'Foo', action: { type: NavigationActions.NAVIGATE, routeName: 'baz' }}, state);
const state3 = router.getStateForAction({ type: NavigationActions.RESET, key: 'Init', actions: [{ type: NavigationActions.NAVIGATE, routeName: 'Foo' }], index: 0 }, state2);
const state4 = router.getStateForAction({ type: NavigationActions.RESET, key: null, actions: [{ type: NavigationActions.NAVIGATE, routeName: 'Bar' }], index: 0 }, state3);
expect(state4 && state4.index).toEqual(0);
expect(state4 && state4.routes[0].routeName).toEqual('Bar');
});
test('Handles the navigate action with params and nested StackRouter', () => {
const ChildNavigator = () => <div />;
ChildNavigator.router = StackRouter({ Baz: { screen: () => <div /> } });