Kill NavigationReducers

Summary:
For navigation actions at high level, reducers from NavigationReducers does not
know anything about the app-specific state thus people won't use these reducers.
Instead, people should build their own reducers.

There are a lot of good libraries available that help people to reducing things if that's
what they really need.

At the low level, for navigation state changes that don't involve app-specific state,
`NavigationStateUtils` should server that kind of need.

`NavigationReducers` serves little benefit cause it does not know the app state, it does
not know how to traverse the navigation states which can be a tree, a list or a map.

That said, we hold no interest in owning in the core navigation library.

Reviewed By: ericvicenti

Differential Revision: D3372910

fbshipit-source-id: 797382b46e7d64b7ad578b51dd37e2b941faa83d
This commit is contained in:
Hedger Wang
2016-06-08 11:33:45 -07:00
committed by Facebook Github Bot 4
parent bb9ed2d24c
commit 3a8b50ad55
10 changed files with 52 additions and 538 deletions

View File

@@ -80,7 +80,7 @@ class YourApplication extends React.Component {
switch (type) {
case 'push':
// push a new route.
const route = {key: Date.now()};
const route = {key: 'route-' + Date.now()};
navigationState = NavigationStateUtils.push(navigationState, route);
break;

View File

@@ -22,27 +22,72 @@
*/
'use strict';
const React = require('react');
const ReactNative = require('react-native');
// $FlowFixMe : This is a platform-forked component, and flow seems to only run on iOS?
const UIExplorerList = require('./UIExplorerList');
const {
NavigationExperimental,
} = ReactNative;
const {
Reducer: NavigationReducer,
StateUtils: NavigationStateUtils,
} = NavigationExperimental;
const StackReducer = NavigationReducer.StackReducer;
import type {NavigationState} from 'NavigationTypeDefinition';
import type {UIExplorerAction} from './UIExplorerActions';
export type UIExplorerNavigationState = {
externalExample: ?string;
stack: NavigationState;
};
const defaultGetReducerForState = (initialState) => (state) => state || initialState;
function StackReducer({initialState, getReducerForState, getPushedReducerForAction}: any): Function {
const getReducerForStateWithDefault = getReducerForState || defaultGetReducerForState;
return function (lastState: ?NavigationState, action: any): NavigationState {
if (!lastState) {
return initialState;
}
const lastParentState = NavigationStateUtils.getParent(lastState);
if (!lastParentState) {
return lastState;
}
const activeSubState = lastParentState.routes[lastParentState.index];
const activeSubReducer = getReducerForStateWithDefault(activeSubState);
const nextActiveState = activeSubReducer(activeSubState, action);
if (nextActiveState !== activeSubState) {
const nextChildren = [...lastParentState.routes];
nextChildren[lastParentState.index] = nextActiveState;
return {
...lastParentState,
routes: nextChildren,
};
}
const subReducerToPush = getPushedReducerForAction(action, lastParentState);
if (subReducerToPush) {
return NavigationStateUtils.push(
lastParentState,
subReducerToPush(null, action)
);
}
switch (action.type) {
case 'back':
case 'BackAction':
if (lastParentState.index === 0 || lastParentState.routes.length === 1) {
return lastParentState;
}
return NavigationStateUtils.pop(lastParentState);
}
return lastParentState;
};
}
const UIExplorerStackReducer = StackReducer({
getPushedReducerForAction: (action, lastState) => {
if (action.type === 'UIExplorerExampleAction' && UIExplorerList.Modules[action.openExample]) {
@@ -106,7 +151,7 @@ function UIExplorerNavigationReducer(lastState: ?UIExplorerNavigationState, acti
return {
externalExample: null,
stack: newStack,
}
};
}
return lastState;
}