From fb0007d85323909ab652bf97166744fa7e17daab Mon Sep 17 00:00:00 2001 From: Hedger Wang Date: Thu, 9 Jun 2016 17:48:39 -0700 Subject: [PATCH] Remove prop `onNavigate`. Summary: Remove prop `onNavigate` from these views. - NavigationAnimatedView - NavigationCardStack - NavigationCard Also, the `sceneProps` onject that is passed to the `renderScene` function no longer contains `onNavigate`. The contract that `onNavigate` expects has been vague. Different data flow system may expect complete different params for such function For instance, * onNavigate({type: 'back'}); * onNavigate({type: 'BACK'}); * onNavigate('back'}); We have no intention to unify such generic API since it's more likely to be constrained by the data flow frameworks such as redux or flux. Also, passing the prop `onNavigate` all the way down to the component that invokes the navigation action can be really tedious. We'd expect developer to either pass such callback (onNavigate) via context or just set up some kind of static actions that any component can call directly. `onNavigate` was previously added as a part of (redux-like) reducers-friendly feature but that's no longer the case. This new prop `onNavigateBack` is used to explicitly handle the case when the back button or back gesture is performed. Reviewed By: ericvicenti Differential Revision: D3410873 fbshipit-source-id: a703cf0debd474cff33d6610e858b9c4bb3ecbf5 --- .../NavigationCardStack-example.js | 5 --- .../NavigationHeaderScenesTabs-example.js | 14 ++++++- Examples/UIExplorer/UIExplorerApp.ios.js | 9 +++-- .../NavigationExperimental/NavigationCard.js | 7 +++- .../NavigationCardStack.js | 16 ++++---- .../NavigationCardStackPanResponder.js | 35 ++++++++--------- .../NavigationHeader.js | 38 +++++++++++-------- .../NavigationHeaderBackButton.js | 8 ++-- .../NavigationPagerPanResponder.js | 29 ++++++-------- .../NavigationAnimatedView.js | 7 ---- .../NavigationPropTypes.js | 2 - .../NavigationTransitioner.js | 7 ---- .../NavigationTypeDefinition.js | 17 --------- 13 files changed, 89 insertions(+), 105 deletions(-) diff --git a/Examples/UIExplorer/NavigationExperimental/NavigationCardStack-example.js b/Examples/UIExplorer/NavigationExperimental/NavigationCardStack-example.js index 6116f04df3a..dae7ad556b5 100644 --- a/Examples/UIExplorer/NavigationExperimental/NavigationCardStack-example.js +++ b/Examples/UIExplorer/NavigationExperimental/NavigationCardStack-example.js @@ -24,8 +24,6 @@ const NavigationExampleRow = require('./NavigationExampleRow'); const React = require('react'); const ReactNative = require('react-native'); -const emptyFunction = require('fbjs/lib/emptyFunction'); - /** * Basic example that shows how to use to build * an app with controlled navigation system. @@ -137,11 +135,8 @@ class YourNavigator extends React.Component { // Now use the `NavigationCardStack` to render the scenes. render(): ReactElement { - // TODO(hedger): prop `onNavigate` will be deprecated soon. For now, - // use `emptyFunction` as a placeholder. return ( ); } + + _back() { + this.props.navigate({type: 'pop'}); + } }); // Next step. @@ -310,6 +315,7 @@ const YourHeader = createAppNavigationContainer(class extends Component { constructor(props: Object, context: any) { super(props, context); + this._back = this._back.bind(this); this._renderTitleComponent = this._renderTitleComponent.bind(this); } @@ -318,11 +324,15 @@ const YourHeader = createAppNavigationContainer(class extends Component { ); } + _back(): void { + this.props.navigate({type: 'pop'}); + } + _renderTitleComponent(): ReactElement { return ( diff --git a/Examples/UIExplorer/UIExplorerApp.ios.js b/Examples/UIExplorer/UIExplorerApp.ios.js index f87cfff9fe9..cb49d2d8a22 100644 --- a/Examples/UIExplorer/UIExplorerApp.ios.js +++ b/Examples/UIExplorer/UIExplorerApp.ios.js @@ -63,11 +63,12 @@ type State = UIExplorerNavigationState & { const APP_STATE_KEY = 'UIExplorerAppState.v1'; class UIExplorerApp extends React.Component { + _handleBack: Function; + _handleAction: Function; + _renderCard: Function; _renderOverlay: Function; _renderScene: Function; - _renderCard: Function; _renderTitleComponent: Function; - _handleAction: Function; state: State; constructor(props: Props) { @@ -76,6 +77,7 @@ class UIExplorerApp extends React.Component { componentWillMount() { this._handleAction = this._handleAction.bind(this); + this._handleBack = this._handleAction.bind(this, {type: 'back'}); this._renderOverlay = this._renderOverlay.bind(this); this._renderScene = this._renderScene.bind(this); this._renderTitleComponent = this._renderTitleComponent.bind(this); @@ -137,7 +139,7 @@ class UIExplorerApp extends React.Component { style={styles.container} renderOverlay={this._renderOverlay} renderScene={this._renderScene} - onNavigate={this._handleAction} + /> ); } @@ -146,6 +148,7 @@ class UIExplorerApp extends React.Component { return ( ); diff --git a/Libraries/CustomComponents/NavigationExperimental/NavigationCard.js b/Libraries/CustomComponents/NavigationExperimental/NavigationCard.js index b4b6aa8ce21..155377ee454 100644 --- a/Libraries/CustomComponents/NavigationExperimental/NavigationCard.js +++ b/Libraries/CustomComponents/NavigationExperimental/NavigationCard.js @@ -57,6 +57,7 @@ type SceneViewProps = { type Props = NavigationSceneRendererProps & { onComponentRef: (ref: any) => void, + onNavigateBack: ?Function, panHandlers: ?NavigationPanPanHandlers, pointerEvents: string, renderScene: NavigationSceneRenderer, @@ -93,6 +94,7 @@ class NavigationCard extends React.Component { static propTypes = { ...NavigationPropTypes.SceneRendererProps, onComponentRef: PropTypes.func.isRequired, + onNavigateBack: PropTypes.func, panHandlers: NavigationPropTypes.panHandlers, pointerEvents: PropTypes.string.isRequired, renderScene: PropTypes.func.isRequired, @@ -121,7 +123,10 @@ class NavigationCard extends React.Component { style; const viewPanHandlers = panHandlers === undefined ? - NavigationCardStackPanResponder.forHorizontal(props) : + NavigationCardStackPanResponder.forHorizontal({ + ...props, + onNavigateBack: this.props.onNavigateBack, + }) : panHandlers; return ( diff --git a/Libraries/CustomComponents/NavigationExperimental/NavigationCardStack.js b/Libraries/CustomComponents/NavigationExperimental/NavigationCardStack.js index 28abd0a4a15..78cb1001e8d 100644 --- a/Libraries/CustomComponents/NavigationExperimental/NavigationCardStack.js +++ b/Libraries/CustomComponents/NavigationExperimental/NavigationCardStack.js @@ -47,7 +47,6 @@ const {PropTypes} = React; const {Directions} = NavigationCardStackPanResponder; import type { - NavigationActionCaller, NavigationState, NavigationSceneRenderer, NavigationSceneRendererProps, @@ -60,9 +59,10 @@ import type { type Props = { direction: NavigationGestureDirection, navigationState: NavigationState, - onNavigate: NavigationActionCaller, + onNavigateBack: ?Function, renderOverlay: ?NavigationSceneRenderer, renderScene: NavigationSceneRenderer, + style: any, }; type DefaultProps = { @@ -90,7 +90,7 @@ class NavigationCardStack extends React.Component { static propTypes = { direction: PropTypes.oneOf([Directions.HORIZONTAL, Directions.VERTICAL]), navigationState: NavigationPropTypes.navigationState.isRequired, - onNavigate: NavigationPropTypes.SceneRendererProps.onNavigate, + onNavigateBack: PropTypes.func, renderOverlay: PropTypes.func, renderScene: PropTypes.func.isRequired, }; @@ -122,8 +122,6 @@ class NavigationCardStack extends React.Component { navigationState={this.props.navigationState} renderOverlay={this.props.renderOverlay} renderScene={this._renderScene} - onNavigate={this.props.onNavigate} - // $FlowFixMe - style should be declared style={[styles.animatedView, this.props.style]} /> ); @@ -136,9 +134,13 @@ class NavigationCardStack extends React.Component { NavigationCardStackStyleInterpolator.forVertical(props) : NavigationCardStackStyleInterpolator.forHorizontal(props); + const panHandlersProps = { + ...props, + onNavigateBack: this.props.onNavigateBack, + }; const panHandlers = isVertical ? - NavigationCardStackPanResponder.forVertical(props) : - NavigationCardStackPanResponder.forHorizontal(props); + NavigationCardStackPanResponder.forVertical(panHandlersProps) : + NavigationCardStackPanResponder.forHorizontal(panHandlersProps); return ( { this._reset(); - if (distance > DISTANCE_THRESHOLD || value <= index - POSITION_THRESHOLD) { - props.onNavigate(Actions.BACK); + + if (!props.onNavigateBack) { + return; + } + + if ( + distance > DISTANCE_THRESHOLD || + value <= index - POSITION_THRESHOLD + ) { + props.onNavigateBack(); } }); } @@ -206,20 +208,20 @@ class NavigationCardStackPanResponder extends NavigationAbstractPanResponder { function createPanHandlers( direction: NavigationGestureDirection, - props: NavigationSceneRendererProps, + props: Props, ): NavigationPanPanHandlers { const responder = new NavigationCardStackPanResponder(direction, props); return responder.panHandlers; } function forHorizontal( - props: NavigationSceneRendererProps, + props: Props, ): NavigationPanPanHandlers { return createPanHandlers(Directions.HORIZONTAL, props); } function forVertical( - props: NavigationSceneRendererProps, + props: Props, ): NavigationPanPanHandlers { return createPanHandlers(Directions.VERTICAL, props); } @@ -232,7 +234,6 @@ module.exports = { RESPOND_THRESHOLD, // enums - Actions, Directions, // methods. diff --git a/Libraries/CustomComponents/NavigationExperimental/NavigationHeader.js b/Libraries/CustomComponents/NavigationExperimental/NavigationHeader.js index 6bde840730b..5603f067743 100644 --- a/Libraries/CustomComponents/NavigationExperimental/NavigationHeader.js +++ b/Libraries/CustomComponents/NavigationExperimental/NavigationHeader.js @@ -48,23 +48,27 @@ const { } = ReactNative; import type { - NavigationActionCaller, - NavigationSceneRenderer, NavigationSceneRendererProps, NavigationStyleInterpolator, } from 'NavigationTypeDefinition'; +type SubViewProps = NavigationSceneRendererProps & { + onNavigateBack: ?Function, +}; + +type SubViewRenderer = (subViewProps: SubViewProps) => ?ReactElement; + type DefaultProps = { - renderLeftComponent: NavigationSceneRenderer, - renderRightComponent: NavigationSceneRenderer, - renderTitleComponent: NavigationSceneRenderer, + renderLeftComponent: SubViewRenderer, + renderRightComponent: SubViewRenderer, + renderTitleComponent: SubViewRenderer, }; type Props = NavigationSceneRendererProps & { - renderLeftComponent: NavigationSceneRenderer, - renderRightComponent: NavigationSceneRenderer, - renderTitleComponent: NavigationSceneRenderer, - onNavigate: NavigationActionCaller, + onNavigateBack: ?Function, + renderLeftComponent: SubViewRenderer, + renderRightComponent: SubViewRenderer, + renderTitleComponent: SubViewRenderer, style?: any, viewProps?: any, }; @@ -80,30 +84,31 @@ class NavigationHeader extends React.Component { static defaultProps = { - renderTitleComponent: (props: NavigationSceneRendererProps) => { + renderTitleComponent: (props: SubViewProps) => { const {navigationState} = props; const title = String(navigationState.title || ''); return {title}; }, - renderLeftComponent: (props: NavigationSceneRendererProps) => { - if (props.scene.index === 0) { + renderLeftComponent: (props: SubViewProps) => { + if (props.scene.index === 0 || !props.onNavigateBack) { return null; } return ( ); }, - renderRightComponent: (props: NavigationSceneRendererProps) => { + renderRightComponent: (props: SubViewProps) => { return null; }, }; static propTypes = { ...NavigationPropTypes.SceneRendererProps, + onNavigateBack: PropTypes.func, renderLeftComponent: PropTypes.func, renderRightComponent: PropTypes.func, renderTitleComponent: PropTypes.func, @@ -167,7 +172,7 @@ class NavigationHeader extends React.Component { _renderSubView( props: NavigationSceneRendererProps, name: SubViewName, - renderer: NavigationSceneRenderer, + renderer: SubViewRenderer, styleInterpolator: NavigationStyleInterpolator, ): ?ReactElement { const { @@ -189,7 +194,8 @@ class NavigationHeader extends React.Component { return null; } - const subView = renderer(props); + const subViewProps = {...props, onNavigateBack: this.props.onNavigateBack}; + const subView = renderer(subViewProps); if (subView === null) { return null; } diff --git a/Libraries/CustomComponents/NavigationExperimental/NavigationHeaderBackButton.js b/Libraries/CustomComponents/NavigationExperimental/NavigationHeaderBackButton.js index 26dd0404b58..097e3b95ba9 100644 --- a/Libraries/CustomComponents/NavigationExperimental/NavigationHeaderBackButton.js +++ b/Libraries/CustomComponents/NavigationExperimental/NavigationHeaderBackButton.js @@ -34,17 +34,17 @@ const { } = ReactNative; type Props = { - onNavigate: Function -} + onPress: Function, +}; const NavigationHeaderBackButton = (props: Props) => ( - props.onNavigate({type: 'BackAction'})}> + ); NavigationHeaderBackButton.propTypes = { - onNavigate: React.PropTypes.func.isRequired + onPress: React.PropTypes.func.isRequired }; const styles = StyleSheet.create({ diff --git a/Libraries/CustomComponents/NavigationExperimental/NavigationPagerPanResponder.js b/Libraries/CustomComponents/NavigationExperimental/NavigationPagerPanResponder.js index b4ed5420cff..86a0e21872b 100644 --- a/Libraries/CustomComponents/NavigationExperimental/NavigationPagerPanResponder.js +++ b/Libraries/CustomComponents/NavigationExperimental/NavigationPagerPanResponder.js @@ -27,7 +27,10 @@ import type { NavigationGestureDirection, } from 'NavigationCardStackPanResponder'; - +type Props = NavigationSceneRendererProps & { + onNavigateBack: ?Function, + onNavigateForward: ?Function, +}; /** * Primitive gesture directions. @@ -40,14 +43,6 @@ const { Directions, } = NavigationCardStackPanResponder; -/** - * Primitive gesture actions. - */ -const Actions = { - JUMP_BACK: {type: 'jump_back'}, - JUMP_FORWARD: {type: 'jump_forward'}, -}; - /** * Pan responder that handles gesture for a card in the cards list. * @@ -66,12 +61,12 @@ class NavigationPagerPanResponder extends NavigationAbstractPanResponder { _isResponding: boolean; _isVertical: boolean; - _props: NavigationSceneRendererProps; + _props: Props; _startValue: number; constructor( direction: NavigationGestureDirection, - props: NavigationSceneRendererProps, + props: Props, ) { super(); this._isResponding = false; @@ -157,7 +152,8 @@ class NavigationPagerPanResponder extends NavigationAbstractPanResponder { const { navigationState, - onNavigate, + onNavigateBack, + onNavigateForward, position, } = this._props; @@ -172,7 +168,7 @@ class NavigationPagerPanResponder extends NavigationAbstractPanResponder { distance > DISTANCE_THRESHOLD || value <= index - POSITION_THRESHOLD ) { - onNavigate(Actions.JUMP_BACK); + onNavigateBack && onNavigateBack(); return; } @@ -180,7 +176,7 @@ class NavigationPagerPanResponder extends NavigationAbstractPanResponder { distance < -DISTANCE_THRESHOLD || value >= index + POSITION_THRESHOLD ) { - onNavigate(Actions.JUMP_FORWARD); + onNavigateForward && onNavigateForward(); } }); } @@ -204,19 +200,18 @@ class NavigationPagerPanResponder extends NavigationAbstractPanResponder { function createPanHandlers( direction: NavigationGestureDirection, - props: NavigationSceneRendererProps, + props: Props, ): NavigationPanPanHandlers { const responder = new NavigationPagerPanResponder(direction, props); return responder.panHandlers; } function forHorizontal( - props: NavigationSceneRendererProps, + props: Props, ): NavigationPanPanHandlers { return createPanHandlers(Directions.HORIZONTAL, props); } module.exports = { - Actions, forHorizontal, }; diff --git a/Libraries/NavigationExperimental/NavigationAnimatedView.js b/Libraries/NavigationExperimental/NavigationAnimatedView.js index 830ab066b52..7b160f6b8c7 100644 --- a/Libraries/NavigationExperimental/NavigationAnimatedView.js +++ b/Libraries/NavigationExperimental/NavigationAnimatedView.js @@ -24,7 +24,6 @@ const StyleSheet = require('StyleSheet'); const View = require('View'); import type { - NavigationActionCaller, NavigationAnimatedValue, NavigationAnimationSetter, NavigationLayout, @@ -36,7 +35,6 @@ import type { type Props = { applyAnimation: NavigationAnimationSetter, navigationState: NavigationState, - onNavigate: NavigationActionCaller, renderOverlay: ?NavigationSceneRenderer, renderScene: NavigationSceneRenderer, style: any, @@ -77,7 +75,6 @@ class NavigationAnimatedView static propTypes = { applyAnimation: PropTypes.func, navigationState: NavigationPropTypes.navigationState.isRequired, - onNavigate: PropTypes.func.isRequired, renderOverlay: PropTypes.func, renderScene: PropTypes.func.isRequired, }; @@ -182,7 +179,6 @@ class NavigationAnimatedView _renderScene(scene: NavigationScene): ?ReactElement { const { navigationState, - onNavigate, renderScene, } = this.props; @@ -195,7 +191,6 @@ class NavigationAnimatedView return renderScene({ layout: this.state.layout, navigationState, - onNavigate, position, progress, scene, @@ -207,7 +202,6 @@ class NavigationAnimatedView if (this.props.renderOverlay) { const { navigationState, - onNavigate, renderOverlay, } = this.props; @@ -220,7 +214,6 @@ class NavigationAnimatedView return renderOverlay({ layout: this.state.layout, navigationState, - onNavigate, position, progress, scene: scenes[navigationState.index], diff --git a/Libraries/NavigationExperimental/NavigationPropTypes.js b/Libraries/NavigationExperimental/NavigationPropTypes.js index d5a4776cc8a..148ffd00310 100644 --- a/Libraries/NavigationExperimental/NavigationPropTypes.js +++ b/Libraries/NavigationExperimental/NavigationPropTypes.js @@ -67,7 +67,6 @@ const scene = PropTypes.shape({ const SceneRendererProps = { layout: layout.isRequired, navigationState: navigationState.isRequired, - onNavigate: PropTypes.func.isRequired, position: animatedValue.isRequired, progress: animatedValue.isRequired, scene: scene.isRequired, @@ -101,7 +100,6 @@ function extractSceneRendererProps( return { layout: props.layout, navigationState: props.navigationState, - onNavigate: props.onNavigate, position: props.position, progress: props.progress, scene: props.scene, diff --git a/Libraries/NavigationExperimental/NavigationTransitioner.js b/Libraries/NavigationExperimental/NavigationTransitioner.js index dc616a1588a..ca613237d44 100644 --- a/Libraries/NavigationExperimental/NavigationTransitioner.js +++ b/Libraries/NavigationExperimental/NavigationTransitioner.js @@ -22,7 +22,6 @@ const View = require('View'); const invariant = require('fbjs/lib/invariant'); import type { - NavigationActionCaller, NavigationAnimatedValue, NavigationLayout, NavigationState, @@ -34,7 +33,6 @@ import type { type Props = { configureTransition: NavigationTransitionConfigurator, navigationState: NavigationState, - onNavigate: NavigationActionCaller, onTransitionEnd: () => void, onTransitionStart: () => void, renderOverlay: ?NavigationSceneRenderer, @@ -71,7 +69,6 @@ class NavigationTransitioner extends React.Component { static propTypes = { configureTransition: PropTypes.func, navigationState: NavigationPropTypes.navigationState.isRequired, - onNavigate: PropTypes.func.isRequired, onTransitionEnd: PropTypes.func, onTransitionStart: PropTypes.func, renderOverlay: PropTypes.func, @@ -186,7 +183,6 @@ class NavigationTransitioner extends React.Component { _renderScene(scene: NavigationScene): ?ReactElement { const { navigationState, - onNavigate, renderScene, } = this.props; @@ -199,7 +195,6 @@ class NavigationTransitioner extends React.Component { return renderScene({ layout: this.state.layout, navigationState, - onNavigate, position, progress, scene, @@ -211,7 +206,6 @@ class NavigationTransitioner extends React.Component { if (this.props.renderOverlay) { const { navigationState, - onNavigate, renderOverlay, } = this.props; @@ -234,7 +228,6 @@ class NavigationTransitioner extends React.Component { return renderOverlay({ layout: this.state.layout, navigationState, - onNavigate, position, progress, scene: activeScene, diff --git a/Libraries/NavigationExperimental/NavigationTypeDefinition.js b/Libraries/NavigationExperimental/NavigationTypeDefinition.js index 15e681b648d..e0eaaa7f7c8 100644 --- a/Libraries/NavigationExperimental/NavigationTypeDefinition.js +++ b/Libraries/NavigationExperimental/NavigationTypeDefinition.js @@ -30,8 +30,6 @@ export type NavigationState = { routes: Array, }; -export type NavigationAction = any; - export type NavigationLayout = { height: NavigationAnimatedValue, initHeight: number, @@ -54,9 +52,6 @@ export type NavigationSceneRendererProps = { // The navigation state of the containing view. navigationState: NavigationState, - // Callback to navigation with an action. - onNavigate: NavigationActionCaller, - // The progressive index of the containing view's navigation state. position: NavigationAnimatedValue, @@ -97,24 +92,12 @@ export type NavigationTransitionSpec = { // Functions. -export type NavigationActionCaller = Function; - export type NavigationAnimationSetter = ( position: NavigationAnimatedValue, newState: NavigationState, lastState: NavigationState, ) => void; -export type NavigationRenderer = ( - navigationState: ?NavigationRoute, - onNavigate: NavigationActionCaller, -) => ReactElement; - -export type NavigationReducer = ( - state: ?NavigationRoute, - action: ?NavigationAction, -) => NavigationRoute; - export type NavigationSceneRenderer = ( props: NavigationSceneRendererProps, ) => ?ReactElement;