Skip to content

Commit

Permalink
StackRouter PopToTop Action (react-navigation#3403)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericvicenti authored and sourcecode911 committed Mar 9, 2020
1 parent 6cb4642 commit 7c4b148
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 1 deletion.
8 changes: 8 additions & 0 deletions src/NavigationActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const BACK = 'Navigation/BACK';
const INIT = 'Navigation/INIT';
const NAVIGATE = 'Navigation/NAVIGATE';
const POP = 'Navigation/POP';
const POP_TO_TOP = 'Navigation/POP_TO_TOP';
const RESET = 'Navigation/RESET';
const SET_PARAMS = 'Navigation/SET_PARAMS';
const URI = 'Navigation/URI';
Expand Down Expand Up @@ -50,6 +51,11 @@ const pop = createAction(POP, payload => ({
immediate: payload && payload.immediate,
}));

const popToTop = createAction(POP_TO_TOP, payload => ({
type: POP_TO_TOP,
immediate: payload && payload.immediate,
}));

const reset = createAction(RESET, payload => ({
type: RESET,
index: payload.index,
Expand Down Expand Up @@ -131,6 +137,7 @@ export default {
INIT,
NAVIGATE,
POP,
POP_TO_TOP,
RESET,
SET_PARAMS,
URI,
Expand All @@ -141,6 +148,7 @@ export default {
init,
navigate,
pop,
popToTop,
reset,
setParams,
uri,
Expand Down
4 changes: 4 additions & 0 deletions src/addNavigationHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export default function(navigation) {
navigation.dispatch(
NavigationActions.pop({ n, immediate: params && params.immediate })
),
popToTop: params =>
navigation.dispatch(
NavigationActions.popToTop({ immediate: params && params.immediate })
),
/**
* For updating current route params. For example the nav bar title and
* buttons are based on the route params.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ exports[`StackNavigator applies correct values when headerRight is present 1`] =
"goBack": [Function],
"navigate": [Function],
"pop": [Function],
"popToTop": [Function],
"setParams": [Function],
"state": Object {
"index": 0,
Expand Down Expand Up @@ -332,6 +333,7 @@ exports[`StackNavigator renders successfully 1`] = `
"goBack": [Function],
"navigate": [Function],
"pop": [Function],
"popToTop": [Function],
"setParams": [Function],
"state": Object {
"index": 0,
Expand Down
14 changes: 13 additions & 1 deletion src/routers/StackRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,19 @@ export default (routeConfigs, stackConfig = {}) => {
}
}

// Handle explicit push navigation action
//Handle pop-to-top behavior. Make sure this happens after children have had a chance to handle the action, so that the inner stack pops to top first.
if (action.type === NavigationActions.POP_TO_TOP) {
if (state.index !== 0) {
return {
isTransitioning: action.immediate !== true,
index: 0,
routes: [state.routes[0]],
};
}
return state;
}

// Handle explicit push navigation action. Make sure this happens after children have had a chance to handle the action
if (
action.type === NavigationActions.NAVIGATE &&
childRouters[action.routeName] !== undefined
Expand Down
36 changes: 36 additions & 0 deletions src/routers/__tests__/StackRouter-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,42 @@ describe('StackRouter', () => {
expect(pushedState.routes[1].routes[1].routeName).toEqual('qux');
});

test('popToTop works as expected', () => {
const TestRouter = StackRouter({
foo: { screen: () => <div /> },
bar: { screen: () => <div /> },
});

const state = {
index: 2,
isTransitioning: false,
routes: [
{ key: 'A', routeName: 'foo' },
{ key: 'B', routeName: 'bar', params: { bazId: '321' } },
{ key: 'C', routeName: 'foo' },
],
};
const poppedState = TestRouter.getStateForAction(
NavigationActions.popToTop(),
state
);
expect(poppedState.routes.length).toBe(1);
expect(poppedState.index).toBe(0);
expect(poppedState.isTransitioning).toBe(true);
const poppedState2 = TestRouter.getStateForAction(
NavigationActions.popToTop(),
poppedState
);
expect(poppedState).toEqual(poppedState2);
const poppedImmediatelyState = TestRouter.getStateForAction(
NavigationActions.popToTop({ immediate: true }),
state
);
expect(poppedImmediatelyState.routes.length).toBe(1);
expect(poppedImmediatelyState.index).toBe(0);
expect(poppedImmediatelyState.isTransitioning).toBe(false);
});

test('Navigate Pushes duplicate routeName', () => {
const TestRouter = StackRouter({
foo: { screen: () => <div /> },
Expand Down
1 change: 1 addition & 0 deletions src/views/__tests__/__snapshots__/TabView-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ exports[`TabBarBottom renders successfully 1`] = `
"goBack": [Function],
"navigate": [Function],
"pop": [Function],
"popToTop": [Function],
"setParams": [Function],
"state": Object {
"key": "s1",
Expand Down

0 comments on commit 7c4b148

Please sign in to comment.