mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-25 21:05:40 +08:00
NavigationExperimental
Summary: A new API to unify internal navigation. Also addresses a highly-rated community 'pain': https://productpains.com/post/react-native/better-navigator-api-and-docs/ Offers the following improvements: - Redux-style navigation logic is easy to reason about - Navigation state can be easily saved and restored through refreshes - Declarative navigation views can be implemented in native or JS - Animations and gestures are isolated and now use the Animated library public Reviewed By: hedgerwang Differential Revision: D2798048 fb-gh-sync-id: 88027ef9ead8a80afa38354252bc377455cc6dbb
This commit is contained in:
committed by
facebook-github-bot-9
parent
2f73ad0241
commit
a3085464f6
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule NavigationTabsReducer
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const NavigationFindReducer = require('NavigationFindReducer');
|
||||
const NavigationStateUtils = require('NavigationState');
|
||||
|
||||
import type {
|
||||
NavigationReducer,
|
||||
NavigationReducerWithDefault,
|
||||
NavigationState
|
||||
} from 'NavigationState';
|
||||
|
||||
const ActionTypes = {
|
||||
JUMP_TO: 'react-native/NavigationExperimental/tabs-jumpTo',
|
||||
ON_TAB_ACTION: 'react-native/NavigationExperimental/tabs-onTabAction',
|
||||
};
|
||||
|
||||
const DEFAULT_KEY = 'TABS_STATE_DEFAULT_KEY';
|
||||
|
||||
export type JumpToAction = {
|
||||
type: typeof ActionTypes.JUMP_TO,
|
||||
index: number,
|
||||
};
|
||||
function NavigationTabsJumpToAction(index: number): JumpToAction {
|
||||
return {
|
||||
type: ActionTypes.JUMP_TO,
|
||||
index,
|
||||
};
|
||||
}
|
||||
|
||||
export type OnTabAction = {
|
||||
type: string,
|
||||
index: number,
|
||||
action: any,
|
||||
};
|
||||
function NavigationTabsOnTabAction(index: number, action: any): OnTabAction {
|
||||
return {
|
||||
type: ActionTypes.ON_TAB_ACTION,
|
||||
index,
|
||||
action,
|
||||
};
|
||||
}
|
||||
|
||||
type TabsReducerConfig = {
|
||||
key: string;
|
||||
initialIndex: ?number;
|
||||
tabReducers: Array<NavigationReducerWithDefault>;
|
||||
};
|
||||
|
||||
function NavigationTabsReducer({key, initialIndex, tabReducers}: TabsReducerConfig): NavigationReducer {
|
||||
if (initialIndex == null) {
|
||||
initialIndex = 0;
|
||||
}
|
||||
if (key == null) {
|
||||
key = DEFAULT_KEY;
|
||||
}
|
||||
return function(lastNavState: ?NavigationState, action: ?any): ?NavigationState {
|
||||
if (!lastNavState) {
|
||||
lastNavState = {
|
||||
children: tabReducers.map(reducer => reducer(null, null)),
|
||||
index: initialIndex,
|
||||
key,
|
||||
};
|
||||
}
|
||||
const lastParentNavState = NavigationStateUtils.getParent(lastNavState);
|
||||
if (!action || !lastParentNavState) {
|
||||
return lastNavState;
|
||||
}
|
||||
if (
|
||||
action.type === ActionTypes.JUMP_TO &&
|
||||
action.index !== lastParentNavState.index
|
||||
) {
|
||||
return NavigationStateUtils.jumpToIndex(
|
||||
lastParentNavState,
|
||||
action.index,
|
||||
);
|
||||
}
|
||||
if (action.type === ActionTypes.ON_TAB_ACTION) {
|
||||
const onTabAction: OnTabAction = action;
|
||||
const lastTabRoute = lastParentNavState.children[onTabAction.index];
|
||||
const tabReducer = tabReducers[onTabAction.index];
|
||||
if (tabReducer) {
|
||||
const newTabRoute = tabReducer(lastTabRoute, action.action);
|
||||
if (newTabRoute && newTabRoute !== lastTabRoute) {
|
||||
let navState = NavigationStateUtils.replaceAtIndex(
|
||||
lastParentNavState,
|
||||
onTabAction.index,
|
||||
newTabRoute
|
||||
);
|
||||
navState = NavigationStateUtils.jumpToIndex(
|
||||
navState,
|
||||
onTabAction.index
|
||||
);
|
||||
return navState;
|
||||
}
|
||||
}
|
||||
}
|
||||
const subReducers = tabReducers.map((tabReducer, tabIndex) => {
|
||||
return function reduceTab(lastTabState: ?NavigationState, tabAction: ?any): ?NavigationState {
|
||||
if (!lastTabState) {
|
||||
return tabReducer(lastTabState, tabAction);
|
||||
}
|
||||
if (!lastParentNavState) {
|
||||
return lastTabState;
|
||||
}
|
||||
const lastSubTabState = lastParentNavState.children[tabIndex];
|
||||
const nextSubTabState = tabReducer(lastSubTabState, tabAction);
|
||||
if (nextSubTabState && lastSubTabState !== nextSubTabState) {
|
||||
const tabs = lastParentNavState.children;
|
||||
tabs[tabIndex] = nextSubTabState;
|
||||
return {
|
||||
...lastParentNavState,
|
||||
tabs,
|
||||
index: tabIndex,
|
||||
};
|
||||
}
|
||||
return lastParentNavState;
|
||||
};
|
||||
});
|
||||
let selectedTabReducer = subReducers.splice(lastParentNavState.index, 1)[0];
|
||||
subReducers.unshift(selectedTabReducer);
|
||||
const findReducer = NavigationFindReducer(subReducers);
|
||||
if (findReducer) {
|
||||
return findReducer(lastParentNavState, action);
|
||||
}
|
||||
return lastParentNavState;
|
||||
};
|
||||
}
|
||||
|
||||
NavigationTabsReducer.JumpToAction = NavigationTabsJumpToAction;
|
||||
NavigationTabsReducer.OnTabAction = NavigationTabsOnTabAction;
|
||||
|
||||
module.exports = NavigationTabsReducer;
|
||||
Reference in New Issue
Block a user