Skip to content

Commit

Permalink
Kill NavigationExperimental Containers
Browse files Browse the repository at this point in the history
Summary:
The containers in NavigationExperimental are not appropraite because the state should be held by the app's architecture, be it redux, flux, or simple component state.

This diff moves the examples over to simple component state, but there are several other examples of how to use NavigationAnimatedView and the navigation reducers with redux:

- https://github.com/jlyman/RN-NavigationExperimental-Redux-Example
- Switching the f8 app with redux to navigation experimental: fbsamples/f8app#14

Reviewed By: hedgerwang

Differential Revision: D3219911

fb-gh-sync-id: eb0b323e2c165c32027fbd00dc6197ad441d6552
fbshipit-source-id: eb0b323e2c165c32027fbd00dc6197ad441d6552
  • Loading branch information
Eric Vicenti authored and Facebook Github Bot 4 committed May 5, 2016
1 parent a412fd1 commit 14eb427
Show file tree
Hide file tree
Showing 22 changed files with 413 additions and 610 deletions.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@ const {
Card: NavigationCard, Card: NavigationCard,
Header: NavigationHeader, Header: NavigationHeader,
Reducer: NavigationReducer, Reducer: NavigationReducer,
RootContainer: NavigationRootContainer,
} = NavigationExperimental; } = NavigationExperimental;


const NavigationBasicReducer = NavigationReducer.StackReducer({ const ExampleReducer = NavigationReducer.StackReducer({
getPushedReducerForAction: (action) => { getPushedReducerForAction: (action) => {
if (action.type === 'push') { if (action.type === 'push') {
return (state) => state || {key: action.key}; return (state) => state || {key: action.key};
Expand All @@ -58,37 +57,41 @@ const NavigationBasicReducer = NavigationReducer.StackReducer({
}); });


class NavigationAnimatedExample extends React.Component { class NavigationAnimatedExample extends React.Component {
constructor(props, context) {
super(props, context);
this.state = ExampleReducer();
}

componentWillMount() { componentWillMount() {
this._renderCard = this._renderCard.bind(this); this._renderCard = this._renderCard.bind(this);
this._renderHeader = this._renderHeader.bind(this); this._renderHeader = this._renderHeader.bind(this);
this._renderNavigation = this._renderNavigation.bind(this);
this._renderScene = this._renderScene.bind(this); this._renderScene = this._renderScene.bind(this);
this._renderTitleComponent = this._renderTitleComponent.bind(this); this._renderTitleComponent = this._renderTitleComponent.bind(this);
this._handleAction = this._handleAction.bind(this);
} }
render() {
return ( _handleAction(action): boolean {
<NavigationRootContainer if (!action) {
reducer={NavigationBasicReducer} return false;
ref={navRootContainer => { this.navRootContainer = navRootContainer; }} }
persistenceKey="NavigationAnimExampleState" const newState = ExampleReducer(this.state, action);
renderNavigation={this._renderNavigation} if (newState === this.state) {
/> return false;
); }
this.setState(newState);
return true;
} }
handleBackAction() {
return ( handleBackAction(): boolean {
this.navRootContainer && return this._handleAction({ type: 'BackAction', });
this.navRootContainer.handleNavigation(NavigationRootContainer.getBackAction())
);
} }
_renderNavigation(navigationState, onNavigate) {
if (!navigationState) { render() {
return null;
}
return ( return (
<NavigationAnimatedView <NavigationAnimatedView
navigationState={navigationState} navigationState={this.state}
style={styles.animatedView} style={styles.animatedView}
onNavigate={this._handleAction}
renderOverlay={this._renderHeader} renderOverlay={this._renderHeader}
applyAnimation={(pos, navState) => { applyAnimation={(pos, navState) => {
Animated.timing(pos, {toValue: navState.index, duration: 500}).start(); Animated.timing(pos, {toValue: navState.index, duration: 500}).start();
Expand Down
Original file line number Original file line Diff line number Diff line change
@@ -1,4 +1,11 @@
/** /**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and * The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only. * evaluation purposes only.
* *
Expand All @@ -22,12 +29,10 @@ const {
} = ReactNative; } = ReactNative;
const NavigationExampleRow = require('./NavigationExampleRow'); const NavigationExampleRow = require('./NavigationExampleRow');
const { const {
RootContainer: NavigationRootContainer,
Reducer: NavigationReducer, Reducer: NavigationReducer,
} = NavigationExperimental; } = NavigationExperimental;
const StackReducer = NavigationReducer.StackReducer;


const NavigationBasicReducer = NavigationReducer.StackReducer({ const ExampleReducer = NavigationReducer.StackReducer({
getPushedReducerForAction: (action) => { getPushedReducerForAction: (action) => {
if (action.type === 'push') { if (action.type === 'push') {
return (state) => state || {key: action.key}; return (state) => state || {key: action.key};
Expand All @@ -45,47 +50,51 @@ const NavigationBasicReducer = NavigationReducer.StackReducer({
}); });


const NavigationBasicExample = React.createClass({ const NavigationBasicExample = React.createClass({

getInitialState: function() {
return ExampleReducer();
},

render: function() { render: function() {
return ( return (
<NavigationRootContainer <ScrollView style={styles.topView}>
reducer={NavigationBasicReducer} <NavigationExampleRow
persistenceKey="NavigationBasicExampleState" text={`Current page: ${this.state.children[this.state.index].key}`}
ref={navRootContainer => { this.navRootContainer = navRootContainer; }} />
renderNavigation={(navState, onNavigate) => { <NavigationExampleRow
if (!navState) { return null; } text={`Push page #${this.state.children.length}`}
return ( onPress={() => {
<ScrollView style={styles.topView}> this._handleAction({ type: 'push', key: 'page #' + this.state.children.length });
<NavigationExampleRow }}
text={`Current page: ${navState.children[navState.index].key}`} />
/> <NavigationExampleRow
<NavigationExampleRow text="pop"
text={`Push page #${navState.children.length}`} onPress={() => {
onPress={() => { this._handleAction({ type: 'BackAction' });
onNavigate({ type: 'push', key: 'page #' + navState.children.length }); }}
}} />
/> <NavigationExampleRow
<NavigationExampleRow text="Exit Basic Nav Example"
text="pop" onPress={this.props.onExampleExit}
onPress={() => { />
onNavigate(NavigationRootContainer.getBackAction()); </ScrollView>
}}
/>
<NavigationExampleRow
text="Exit Basic Nav Example"
onPress={this.props.onExampleExit}
/>
</ScrollView>
);
}}
/>
); );
}, },


handleBackAction: function() { _handleAction(action) {
return ( if (!action) {
this.navRootContainer && return false;
this.navRootContainer.handleNavigation(NavigationRootContainer.getBackAction()) }
); const newState = ExampleReducer(this.state, action);
if (newState === this.state) {
return false;
}
this.setState(newState);
return true;
},

handleBackAction() {
return this._handleAction({ type: 'BackAction' });
}, },


}); });
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -33,18 +33,15 @@ const {
const { const {
CardStack: NavigationCardStack, CardStack: NavigationCardStack,
StateUtils: NavigationStateUtils, StateUtils: NavigationStateUtils,
RootContainer: NavigationRootContainer,
} = NavigationExperimental; } = NavigationExperimental;


function createReducer(initialState) { function createReducer(initialState) {
return (currentState, action) => { return (currentState = initialState, action) => {
switch (action.type) { switch (action.type) {
case 'RootContainerInitialAction':
return initialState;

case 'push': case 'push':
return NavigationStateUtils.push(currentState, {key: action.key}); return NavigationStateUtils.push(currentState, {key: action.key});


case 'BackAction':
case 'back': case 'back':
case 'pop': case 'pop':
return currentState.index > 0 ? return currentState.index > 0 ?
Expand All @@ -67,37 +64,48 @@ class NavigationCardStackExample extends React.Component {


constructor(props, context) { constructor(props, context) {
super(props, context); super(props, context);
this.state = {isHorizontal: true}; this.state = {
isHorizontal: true,
navState: ExampleReducer(undefined, {}),
};
} }


componentWillMount() { componentWillMount() {
this._renderNavigation = this._renderNavigation.bind(this);
this._renderScene = this._renderScene.bind(this); this._renderScene = this._renderScene.bind(this);
this._toggleDirection = this._toggleDirection.bind(this); this._toggleDirection = this._toggleDirection.bind(this);
this._handleAction = this._handleAction.bind(this);
} }


render() { render() {
return (
<NavigationRootContainer
reducer={ExampleReducer}
renderNavigation={this._renderNavigation}
style={styles.main}
/>
);
}

_renderNavigation(navigationState, onNavigate) {
return ( return (
<NavigationCardStack <NavigationCardStack
direction={this.state.isHorizontal ? 'horizontal' : 'vertical'} direction={this.state.isHorizontal ? 'horizontal' : 'vertical'}
navigationState={navigationState} navigationState={this.state.navState}
onNavigate={onNavigate} onNavigate={this._handleAction}
renderScene={this._renderScene} renderScene={this._renderScene}
style={styles.main} style={styles.main}
/> />
); );
} }


_handleAction(action): boolean {
if (!action) {
return false;
}
const newState = ExampleReducer(this.state.navState, action);
if (newState === this.state.navState) {
return false;
}
this.setState({
navState: newState,
});
return true;
}

handleBackAction(): boolean {
return this._handleAction({ type: 'BackAction', });
}

_renderScene(/*NavigationSceneRendererProps*/ props) { _renderScene(/*NavigationSceneRendererProps*/ props) {
return ( return (
<ScrollView style={styles.scrollView}> <ScrollView style={styles.scrollView}>
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -36,10 +36,8 @@ const {


const { const {
CardStack: NavigationCardStack, CardStack: NavigationCardStack,
Container: NavigationContainer,
Header: NavigationHeader, Header: NavigationHeader,
Reducer: NavigationReducer, Reducer: NavigationReducer,
RootContainer: NavigationRootContainer,
View: NavigationView, View: NavigationView,
} = NavigationExperimental; } = NavigationExperimental;


Expand Down Expand Up @@ -177,6 +175,7 @@ class ExampleTabScreen extends React.Component {
<NavigationCardStack <NavigationCardStack
style={styles.tabContent} style={styles.tabContent}
navigationState={this.props.navigationState} navigationState={this.props.navigationState}
onNavigate={this.props.onNavigate}
renderOverlay={this._renderHeader} renderOverlay={this._renderHeader}
renderScene={this._renderScene} renderScene={this._renderScene}
/> />
Expand Down Expand Up @@ -225,40 +224,42 @@ class ExampleTabScreen extends React.Component {
); );
} }
} }
ExampleTabScreen = NavigationContainer.create(ExampleTabScreen);


class NavigationCompositionExample extends React.Component { class NavigationCompositionExample extends React.Component {
navRootContainer: NavigationRootContainer; state: NavigationParentState;

constructor() {
render() { super();
return ( this.state = ExampleAppReducer(undefined, {});
<NavigationRootContainer }
reducer={ExampleAppReducer} handleAction(action: Object): boolean {
persistenceKey="NavigationCompositionState" if (!action) {
ref={navRootContainer => { this.navRootContainer = navRootContainer; }} return false;
renderNavigation={this.renderApp.bind(this)} }
/> const newState = ExampleAppReducer(this.state, action);
); if (newState === this.state) {
return false;
}
this.setState(newState);
return true;
} }
handleBackAction(): boolean { handleBackAction(): boolean {
return ( return this.handleAction({ type: 'BackAction' });
this.navRootContainer &&
this.navRootContainer.handleNavigation(NavigationRootContainer.getBackAction())
);
} }
renderApp(navigationState: NavigationParentState, onNavigate: Function) { render() {
if (!navigationState) { if (!this.state) {
return null; return null;
} }
return ( return (
<View style={styles.topView}> <View style={styles.topView}>
<ExampleMainView <ExampleMainView
navigationState={navigationState} navigationState={this.state}
onExampleExit={this.props.onExampleExit} onExampleExit={this.props.onExampleExit}
onNavigate={this.handleAction.bind(this)}
/> />
<NavigationExampleTabBar <NavigationExampleTabBar
tabs={navigationState.children} tabs={this.state.children}
index={navigationState.index} index={this.state.index}
onNavigate={this.handleAction.bind(this)}
/> />
</View> </View>
); );
Expand All @@ -267,15 +268,18 @@ class NavigationCompositionExample extends React.Component {


class ExampleMainView extends React.Component { class ExampleMainView extends React.Component {
_renderScene: NavigationSceneRenderer; _renderScene: NavigationSceneRenderer;
_handleNavigation: Function;


componentWillMount() { componentWillMount() {
this._renderScene = this._renderScene.bind(this); this._renderScene = this._renderScene.bind(this);
this._handleNavigation = this._handleNavigation.bind(this);
} }


render() { render() {
return ( return (
<NavigationView <NavigationView
navigationState={this.props.navigationState} navigationState={this.props.navigationState}
onNavigate={this._handleNavigation}
style={styles.tabsContent} style={styles.tabsContent}
renderScene={this._renderScene} renderScene={this._renderScene}
/> />
Expand All @@ -288,12 +292,12 @@ class ExampleMainView extends React.Component {
<ExampleTabScreen <ExampleTabScreen
key={'tab_screen' + scene.key} key={'tab_screen' + scene.key}
navigationState={scene.navigationState} navigationState={scene.navigationState}
onNavigate={this._handleNavigation.bind(this, scene.key)} onNavigate={this._handleNavigation}
/> />
); );
} }


_handleNavigation(tabKey, action) { _handleNavigation(action: Object) {
if (ExampleExitAction.match(action)) { if (ExampleExitAction.match(action)) {
this.props.onExampleExit(); this.props.onExampleExit();
return; return;
Expand All @@ -302,8 +306,6 @@ class ExampleMainView extends React.Component {
} }
} }


ExampleMainView = NavigationContainer.create(ExampleMainView);

const styles = StyleSheet.create({ const styles = StyleSheet.create({
topView: { topView: {
flex: 1, flex: 1,
Expand Down
Loading

0 comments on commit 14eb427

Please sign in to comment.