mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-02-10 09:13:43 +08:00
Make TabRouter handle COMPLETE_TRANSITION in a child router without switching active index (#3473)
This commit is contained in:
@@ -6,6 +6,13 @@ import NavigationActions from '../NavigationActions';
|
||||
import validateRouteConfigMap from './validateRouteConfigMap';
|
||||
import getScreenConfigDeprecated from './getScreenConfigDeprecated';
|
||||
|
||||
function childrenUpdateWithoutSwitchingIndex(actionType) {
|
||||
return [
|
||||
NavigationActions.SET_PARAMS,
|
||||
NavigationActions.COMPLETE_TRANSITION,
|
||||
].includes(actionType);
|
||||
}
|
||||
|
||||
export default (routeConfigs, config = {}) => {
|
||||
// Fail fast on invalid route definitions
|
||||
validateRouteConfigMap(routeConfigs);
|
||||
@@ -213,9 +220,13 @@ export default (routeConfigs, config = {}) => {
|
||||
});
|
||||
// console.log(`${order.join('-')}: Processed other tabs:`, {lastIndex: state.index, index});
|
||||
|
||||
// keep active tab index if action type is SET_PARAMS
|
||||
index =
|
||||
action.type === NavigationActions.SET_PARAMS ? state.index : index;
|
||||
// Nested routers can be updated after switching tabs with actions such as SET_PARAMS
|
||||
// and COMPLETE_TRANSITION.
|
||||
// NOTE: This may be problematic with custom routers because we whitelist the actions
|
||||
// that can be handled by child routers without automatically changing index.
|
||||
if (childrenUpdateWithoutSwitchingIndex(action.type)) {
|
||||
index = state.index;
|
||||
}
|
||||
|
||||
if (index !== state.index || routes !== state.routes) {
|
||||
return {
|
||||
|
||||
@@ -8,6 +8,12 @@ import TabRouter from '../TabRouter';
|
||||
import NavigationActions from '../../NavigationActions';
|
||||
import addNavigationHelpers from '../../addNavigationHelpers';
|
||||
|
||||
import { _TESTING_ONLY_normalize_keys } from '../KeyGenerator';
|
||||
|
||||
beforeEach(() => {
|
||||
_TESTING_ONLY_normalize_keys();
|
||||
});
|
||||
|
||||
const ROUTERS = {
|
||||
TabRouter,
|
||||
StackRouter,
|
||||
@@ -105,8 +111,8 @@ test('Handles no-op actions with tabs within stack router', () => {
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'Qux',
|
||||
});
|
||||
expect(state1.routes[0].key).toEqual('Init-id-0-0');
|
||||
expect(state2.routes[0].key).toEqual('Init-id-0-1');
|
||||
expect(state1.routes[0].key).toEqual('Init-id-0');
|
||||
expect(state2.routes[0].key).toEqual('Init-id-1');
|
||||
state1.routes[0].key = state2.routes[0].key;
|
||||
expect(state1).toEqual(state2);
|
||||
const state3 = TestRouter.getStateForAction(
|
||||
@@ -134,7 +140,7 @@ test('Handles deep action', () => {
|
||||
key: 'StackRouterRoot',
|
||||
routes: [
|
||||
{
|
||||
key: 'Init-id-0-2',
|
||||
key: 'Init-id-0',
|
||||
routeName: 'Bar',
|
||||
},
|
||||
],
|
||||
@@ -174,8 +180,8 @@ test('Supports lazily-evaluated getScreen', () => {
|
||||
immediate: true,
|
||||
routeName: 'Qux',
|
||||
});
|
||||
expect(state1.routes[0].key).toEqual('Init-id-0-4');
|
||||
expect(state2.routes[0].key).toEqual('Init-id-0-5');
|
||||
expect(state1.routes[0].key).toEqual('Init-id-0');
|
||||
expect(state2.routes[0].key).toEqual('Init-id-1');
|
||||
state1.routes[0].key = state2.routes[0].key;
|
||||
expect(state1).toEqual(state2);
|
||||
const state3 = TestRouter.getStateForAction(
|
||||
@@ -188,3 +194,60 @@ test('Supports lazily-evaluated getScreen', () => {
|
||||
);
|
||||
expect(state2).toEqual(state3);
|
||||
});
|
||||
|
||||
test('Does not switch tab index when TabRouter child handles COMPLETE_NAVIGATION or SET_PARAMS', () => {
|
||||
const FooStackNavigator = () => <div />;
|
||||
const BarView = () => <div />;
|
||||
FooStackNavigator.router = StackRouter({
|
||||
Foo: {
|
||||
screen: BarView,
|
||||
},
|
||||
Bar: {
|
||||
screen: BarView,
|
||||
},
|
||||
});
|
||||
|
||||
const TestRouter = TabRouter({
|
||||
Zap: { screen: FooStackNavigator },
|
||||
Zoo: { screen: FooStackNavigator },
|
||||
});
|
||||
|
||||
const state1 = TestRouter.getStateForAction({ type: NavigationActions.INIT });
|
||||
|
||||
// Navigate to the second screen in the first tab
|
||||
const state2 = TestRouter.getStateForAction(
|
||||
{
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'Bar',
|
||||
},
|
||||
state1
|
||||
);
|
||||
|
||||
// Switch tabs
|
||||
const state3 = TestRouter.getStateForAction(
|
||||
{
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'Zoo',
|
||||
},
|
||||
state2
|
||||
);
|
||||
|
||||
const stateAfterCompleteTransition = TestRouter.getStateForAction(
|
||||
{
|
||||
type: NavigationActions.COMPLETE_TRANSITION,
|
||||
key: state2.routes[0].key,
|
||||
},
|
||||
state3
|
||||
);
|
||||
const stateAfterSetParams = TestRouter.getStateForAction(
|
||||
{
|
||||
type: NavigationActions.SET_PARAMS,
|
||||
key: state1.routes[0].routes[0].key,
|
||||
params: { key: 'value' },
|
||||
},
|
||||
state3
|
||||
);
|
||||
|
||||
expect(stateAfterCompleteTransition.index).toEqual(1);
|
||||
expect(stateAfterSetParams.index).toEqual(1);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user