From 13e0d2a27828760e510dd8dc73624366eb98493b Mon Sep 17 00:00:00 2001 From: Jake Murzy Date: Mon, 6 Jun 2016 22:48:53 -0700 Subject: [PATCH] bring it up to date with latest changes in NavigationExperimental - [x] bump react - [x] bump react-native - [x] bump react-router --- .../app/components/Discover/Header.ios.js | 2 +- examples/Aviato/app/components/index.ios.js | 6 +- examples/Aviato/app/routes.js | 5 +- examples/Aviato/package.json | 6 +- modules/Reducer.js | 6 +- modules/ReducerUtils.js | 131 +++++++++-------- modules/RootWrapper.js | 17 +-- modules/RouteUtils.js | 4 +- modules/RouteView.js | 38 ++--- modules/RouterContext.js | 38 ++--- modules/StackRoute.js | 4 +- modules/StackRouteView.js | 60 ++++---- modules/TabsRouteView.js | 59 ++++---- modules/TypeDefinition.js | 8 +- modules/nativeHistory.js | 134 +++++++++--------- modules/transitionRegistry.js | 14 +- modules/warningUtil.js | 16 +-- package.json | 10 +- 18 files changed, 284 insertions(+), 274 deletions(-) diff --git a/examples/Aviato/app/components/Discover/Header.ios.js b/examples/Aviato/app/components/Discover/Header.ios.js index 621d57a..2255a19 100644 --- a/examples/Aviato/app/components/Discover/Header.ios.js +++ b/examples/Aviato/app/components/Discover/Header.ios.js @@ -23,7 +23,7 @@ export default class Header extends Component { renderTitleComponent(props) { const { scene } = props; - const title = String(scene.navigationState.key || ''); + const title = String(scene.route.key || ''); return ( {title} diff --git a/examples/Aviato/app/components/index.ios.js b/examples/Aviato/app/components/index.ios.js index a4fa133..0bfe4c5 100644 --- a/examples/Aviato/app/components/index.ios.js +++ b/examples/Aviato/app/components/index.ios.js @@ -1,6 +1,6 @@ /* @noflow */ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; import { NavigationExperimental, View, @@ -37,7 +37,7 @@ export const stackHeaderComponent = (backgroundColor, marginTop = 0) => { renderTitleComponent(props) { const { scene } = props; - const title = String(scene.navigationState.key || ''); + const title = String(scene.route.key || ''); return ( {title} @@ -89,7 +89,7 @@ export const tabHeaderComponent = (backgroundColor, marginTop = 0) => { renderTitleComponent(props) { const { scene } = props; - const title = String(scene.navigationState.key || ''); + const title = String(scene.route.key || ''); return ( {title} diff --git a/examples/Aviato/app/routes.js b/examples/Aviato/app/routes.js index 2538586..b1f8174 100644 --- a/examples/Aviato/app/routes.js +++ b/examples/Aviato/app/routes.js @@ -24,7 +24,6 @@ import { NAVIGATION_HEADER_HEIGHT } from './components/styles'; const SECOND_HEADER = NAVIGATION_HEADER_HEIGHT; const THIRD_HEADER = NAVIGATION_HEADER_HEIGHT * 2; - /** * NOTE: The route hierarchy below is deliberately complex to demonstrate all * capabilities of this library, don't approach the information architecture @@ -43,8 +42,8 @@ const THIRD_HEADER = NAVIGATION_HEADER_HEIGHT * 2; * - has a 'public' ('/', entry point of the app) and a 'private' section * (/home/user/private) which can be navigated by two buttons in the bottom * of the page - * - The 'private' section (/home/user/private) again has some subroutes, - * which can be navigated to by opening the side menu and + * - The 'private' section (/home/user/private) again has some subroutes, + * which can be navigated to by opening the side menu and * selecting 'Private settings' or 'Private Info' * - a 'Following' (/home/following) tab * - a 'Bar' tab (/home/following-bar), a parameterized version of the 'Following' tab diff --git a/examples/Aviato/package.json b/examples/Aviato/package.json index ca97566..3f8fc30 100644 --- a/examples/Aviato/package.json +++ b/examples/Aviato/package.json @@ -6,10 +6,10 @@ "start": "node node_modules/react-native/local-cli/cli.js start" }, "dependencies": { - "react": "15.1.0-alpha.1", - "react-native": "v0.27.0-rc", + "react": "^15.1.0", + "react-native": "0.28.0-rc.0", "react-native-side-menu": "^0.19.0", - "react-router": "^2.3.0", + "react-router": "3.0.0-alpha.1", "react-router-native": "file:../../" } } diff --git a/modules/Reducer.js b/modules/Reducer.js index 6cad67c..fdfb433 100644 --- a/modules/Reducer.js +++ b/modules/Reducer.js @@ -1,12 +1,12 @@ /* @flow */ import { defaultReducer } from './ReducerUtils'; -import type { EnhancedNavigationState, NavigationAction } from './TypeDefinition'; +import type { EnhancedNavigationRoute, NavigationAction } from './TypeDefinition'; export default ( - state: ?EnhancedNavigationState, + state: ?EnhancedNavigationRoute, action: NavigationAction, -): EnhancedNavigationState => { +): EnhancedNavigationRoute => { const { nextNavigationState } = action; if (!state) { diff --git a/modules/ReducerUtils.js b/modules/ReducerUtils.js index a130861..edce86f 100644 --- a/modules/ReducerUtils.js +++ b/modules/ReducerUtils.js @@ -6,7 +6,7 @@ import getRouteParams from 'react-router/es6/getRouteParams'; import { RouteTypes } from './RouteUtils'; import type { - EnhancedNavigationState, + EnhancedNavigationRoute, Location, RouteDef, IndexRouteDef, @@ -19,7 +19,7 @@ export const LOCATION_CHANGE = '@@router-native/LOCATION_CHANGE'; const { STACK_ROUTE, TABS_ROUTE, ROUTE } = RouteTypes; -const hasNextChild = leaf => leaf.children && leaf.children.length === 1; +const hasNextChild = leaf => leaf.routes && leaf.routes.length === 1; const extractCapturedState = leaf => ({ params: leaf.params, @@ -28,9 +28,9 @@ const extractCapturedState = leaf => ({ }); export function defaultReducer( - state: EnhancedNavigationState, + state: EnhancedNavigationRoute, action: NavigationAction, -): EnhancedNavigationState { +): EnhancedNavigationRoute { const { nextNavigationState: nextState } = action; invariant( @@ -46,9 +46,9 @@ export function defaultReducer( } export function defaultRouteReducer( - state: EnhancedNavigationState, + state: EnhancedNavigationRoute, action: NavigationAction, -): EnhancedNavigationState { +): EnhancedNavigationRoute { invariant( state.type === ROUTE, '`%s` is configured with an invalid reducer.', @@ -58,18 +58,18 @@ export function defaultRouteReducer( const { nextNavigationState: nextState } = action; // `creteState()` always returns a unary tree - const nextLeaf = nextState.children[0]; + const nextLeaf = nextState.routes[0]; if (!nextLeaf) { // Return `nextState` to reset state, or `state` to maintain state return nextState; } - const foundIndex = state.children.findIndex(leaf => nextLeaf && leaf.key === nextLeaf.key); + const foundIndex = state.routes.findIndex(leaf => nextLeaf && leaf.key === nextLeaf.key); const foundNextLeaf = foundIndex > -1; if (foundNextLeaf) { - const foundLeaf = state.children[foundIndex]; + const foundLeaf = state.routes[foundIndex]; // `nextLeaf` has one child, always. See `createState()` if (hasNextChild(nextLeaf)) { const nextAction: NavigationAction = { @@ -79,10 +79,10 @@ export function defaultRouteReducer( return { ...state, - children: [ - ...state.children.slice(0, foundIndex), + routes: [ + ...state.routes.slice(0, foundIndex), defaultReducer(foundLeaf, nextAction), - ...state.children.slice(foundIndex + 1, state.children.length), + ...state.routes.slice(foundIndex + 1, state.routes.length), ], index: foundIndex, ...extractCapturedState(nextState), @@ -92,13 +92,13 @@ export function defaultRouteReducer( // nextLeaf is the final leaf (nextState has no grandchild), update index and stop return { ...state, - children: [ - ...state.children.slice(0, foundIndex), + routes: [ + ...state.routes.slice(0, foundIndex), { ...foundLeaf, ...extractCapturedState(nextLeaf), }, - ...state.children.slice(foundIndex + 1, state.children.length), + ...state.routes.slice(foundIndex + 1, state.routes.length), ], index: foundIndex, ...extractCapturedState(nextState), @@ -108,7 +108,7 @@ export function defaultRouteReducer( // Replace existing child return { ...state, - children: [ + routes: [ nextLeaf, ], index: 0, @@ -117,9 +117,9 @@ export function defaultRouteReducer( } export function defaultTabsRouteReducer( - state: EnhancedNavigationState, + state: EnhancedNavigationRoute, action: NavigationAction, -): EnhancedNavigationState { +): EnhancedNavigationRoute { invariant( state.type === TABS_ROUTE, '`%s` is configured with an invalid reducer.', @@ -129,18 +129,18 @@ export function defaultTabsRouteReducer( const { nextNavigationState: nextState } = action; // `creteState()` always returns a unary tree - const nextLeaf = nextState.children[0]; + const nextLeaf = nextState.routes[0]; if (!nextLeaf) { // Return `nextState` to reset state, or `state` to maintain state return nextState; } - const foundIndex = state.children.findIndex(leaf => nextLeaf && leaf.key === nextLeaf.key); + const foundIndex = state.routes.findIndex(leaf => nextLeaf && leaf.key === nextLeaf.key); const foundNextLeaf = foundIndex > -1; if (foundNextLeaf) { - const foundLeaf = state.children[foundIndex]; + const foundLeaf = state.routes[foundIndex]; // `nextLeaf` has one child, always. See `createState()` if (hasNextChild(nextLeaf)) { const nextAction: NavigationAction = { @@ -150,10 +150,10 @@ export function defaultTabsRouteReducer( return { ...state, - children: [ - ...state.children.slice(0, foundIndex), + routes: [ + ...state.routes.slice(0, foundIndex), defaultReducer(foundLeaf, nextAction), - ...state.children.slice(foundIndex + 1, state.children.length), + ...state.routes.slice(foundIndex + 1, state.routes.length), ], index: foundIndex, ...extractCapturedState(nextState), @@ -163,13 +163,13 @@ export function defaultTabsRouteReducer( // nextLeaf is the final leaf (nextState has no grandchild), update index and stop return { ...state, - children: [ - ...state.children.slice(0, foundIndex), + routes: [ + ...state.routes.slice(0, foundIndex), { ...foundLeaf, ...extractCapturedState(nextLeaf), }, - ...state.children.slice(foundIndex + 1, state.children.length), + ...state.routes.slice(foundIndex + 1, state.routes.length), ], index: foundIndex, ...extractCapturedState(nextState), @@ -179,19 +179,19 @@ export function defaultTabsRouteReducer( // Push a new child return { ...state, - children: [ - ...state.children, + routes: [ + ...state.routes, nextLeaf, ], - index: state.children.length, + index: state.routes.length, ...extractCapturedState(nextState), }; } export function defaultStackRouteReducer( - state: EnhancedNavigationState, + state: EnhancedNavigationRoute, action: NavigationAction, -): EnhancedNavigationState { +): EnhancedNavigationRoute { invariant( state.type === STACK_ROUTE, '`%s` is configured with an invalid reducer.', @@ -201,18 +201,18 @@ export function defaultStackRouteReducer( const { nextNavigationState: nextState } = action; // `creteState()` always returns a unary tree - const nextLeaf = nextState.children[0]; + const nextLeaf = nextState.routes[0]; if (!nextLeaf) { // Return `nextState` to reset state, or `state` to maintain state return nextState; } - const foundIndex = state.children.findIndex(leaf => nextLeaf && leaf.key === nextLeaf.key); + const foundIndex = state.routes.findIndex(leaf => nextLeaf && leaf.key === nextLeaf.key); const foundNextLeaf = foundIndex > -1; if (foundNextLeaf) { - const foundLeaf = state.children[foundIndex]; + const foundLeaf = state.routes[foundIndex]; // `nextLeaf` has one child, always. See `createState()` if (hasNextChild(nextLeaf)) { const nextAction: NavigationAction = { @@ -222,10 +222,10 @@ export function defaultStackRouteReducer( return { ...state, - children: [ - ...state.children.slice(0, foundIndex), + routes: [ + ...state.routes.slice(0, foundIndex), defaultReducer(foundLeaf, nextAction), - ...state.children.slice(foundIndex + 1, state.children.length), + ...state.routes.slice(foundIndex + 1, state.routes.length), ], index: foundIndex, ...extractCapturedState(nextState), @@ -237,8 +237,8 @@ export function defaultStackRouteReducer( // and slice off the tail return { ...state, - children: [ - ...state.children.slice(0, foundIndex + 1), + routes: [ + ...state.routes.slice(0, foundIndex + 1), ], index: foundIndex, ...extractCapturedState(nextState), @@ -248,11 +248,11 @@ export function defaultStackRouteReducer( // Push a new child return { ...state, - children: [ - ...state.children, + routes: [ + ...state.routes, nextLeaf, ], - index: state.children.length, + index: state.routes.length, ...extractCapturedState(nextState), }; } @@ -279,17 +279,20 @@ function getNoPathRoute(route: RouteDef): ?NoPathRouteDef { return null; } -export function createState(routes: any, - location: Location, - params: Object): EnhancedNavigationState { +export function createState( + routes: any, + location: Location, + params: Object +): EnhancedNavigationRoute { /* eslint-disable consistent-return */ - function reduceRoutes(prevState: EnhancedNavigationState, - currentRoute: RouteDef, - index: number, - allRoutes: Array): EnhancedNavigationState { + function reduceRoutes( + prevState: EnhancedNavigationRoute, + currentRoute: RouteDef, + index: number, + allRoutes: Array + ): EnhancedNavigationRoute { let parentRoute; - if (index > 0) { parentRoute = allRoutes[index - 1]; } @@ -335,7 +338,7 @@ export function createState(routes: any, const state = { key, index: 0, - children: [], + routes: [], path, type, routeParams, @@ -349,7 +352,7 @@ export function createState(routes: any, return { ...state, index: 0, - children: [prevState], + routes: [prevState], }; } @@ -363,16 +366,18 @@ export function createState(routes: any, return routes.reduceRight(reduceRoutes, null); } -const canPop = (pos: number, state: EnhancedNavigationState) => { +const canPop = (pos: number, state: EnhancedNavigationRoute) => { const index = state.index + pos; return index >= 0; }; -export function canPopActiveStack(n: number, - leafState: EnhancedNavigationState, - parentState: ?EnhancedNavigationState): ?Location { - if (leafState.children && leafState.children.length > 0) { - return canPopActiveStack(n, leafState.children[leafState.index], leafState); +export function canPopActiveStack( + n: number, + leafState: EnhancedNavigationRoute, + parentState: ?EnhancedNavigationRoute +): ?Location { + if (leafState.routes && leafState.routes.length > 0) { + return canPopActiveStack(n, leafState.routes[leafState.index], leafState); } // Can pop only if active leaf is of a stack @@ -388,7 +393,7 @@ export function canPopActiveStack(n: number, } const popTo = parentState.index + n; - return parentState.children[popTo].location; + return parentState.routes[popTo].location; } warning( @@ -415,9 +420,9 @@ export function getActiveParentRouteType(routes: Array): ?RouteType { return getActiveRouteTypeAtIndex(routes.length - 2, routes); } -export function getActiveLocation(leafState: EnhancedNavigationState): ?Location { - if (leafState.children && leafState.children.length > 0) { - return getActiveLocation(leafState.children[leafState.index]); +export function getActiveLocation(leafState: EnhancedNavigationRoute): ?Location { + if (leafState.routes && leafState.routes.length > 0) { + return getActiveLocation(leafState.routes[leafState.index]); } return leafState.location; diff --git a/modules/RootWrapper.js b/modules/RootWrapper.js index 03ef495..cc6050a 100644 --- a/modules/RootWrapper.js +++ b/modules/RootWrapper.js @@ -6,7 +6,7 @@ import invariant from 'invariant'; import warnOnce from './warningUtil'; import AddressBar from './AddressBar'; import { PAN_RESPONDER_BACK_ACTION } from './transitionRegistry'; -import type { EnhancedNavigationState, Location } from './TypeDefinition'; +import type { EnhancedNavigationRoute, Location } from './TypeDefinition'; import { ADDDRESS_BAR_HEIGHT, globalStyles as styles } from './styles'; @@ -14,7 +14,7 @@ const NAVIGATION_HEADER_BACK_BUTTON_BACK_ACTION = 'BackAction'; type Props = { navigationTree: ReactElement, - navState: EnhancedNavigationState, + navigationState: EnhancedNavigationRoute, location: Location, addressBar: boolean, }; @@ -27,7 +27,7 @@ class RootWrapper extends Component { static propTypes = { navigationTree: PropTypes.element.isRequired, - navState: PropTypes.object.isRequired, + navigationState: PropTypes.object.isRequired, location: PropTypes.object.isRequired, addressBar: PropTypes.bool, }; @@ -80,20 +80,21 @@ class RootWrapper extends Component { ); } - renderNavigation(navigationState: EnhancedNavigationState): ?ReactElement { + renderNavigation(navigationState: EnhancedNavigationRoute): ?ReactElement { const { navigationTree } = this.props; if (!navigationState) { return null; } - return React.cloneElement(navigationTree, { _navigationState: navigationState }); + return React.cloneElement(navigationTree, { navigationState }); } render(): ReactElement { - const { navState, addressBar: isShown, location } = this.props; + const { navigationState, addressBar: isShown, location } = this.props; // TODO react-native does not accept `-reverse` values for `flex-direction`. We need to render - // after navigational components to keep it on top. See react-native/pull/6473 + // after navigational components to keep it on top. See + // react-native/pull/6473|7825 let rootStyles; if (isShown) { @@ -104,7 +105,7 @@ class RootWrapper extends Component { return ( - {this.renderNavigation(navState)} + {this.renderNavigation(navigationState)} ); diff --git a/modules/RouteUtils.js b/modules/RouteUtils.js index 579d73f..6921acd 100644 --- a/modules/RouteUtils.js +++ b/modules/RouteUtils.js @@ -58,7 +58,7 @@ function createNavigationTree(createElement: ElementProvider, } if (route.childRoutes) { - props.navScenes = route.childRoutes.map( + props.navigationScenes = route.childRoutes.map( (r, index) => createNavigationTree(createElement, routes, r, index) ); @@ -76,7 +76,7 @@ function createNavigationTree(createElement: ElementProvider, const indexRouteEl = createElement(RouteView, indexRouteProps); - props.navScenes.unshift(indexRouteEl); + props.navigationScenes.unshift(indexRouteEl); } } diff --git a/modules/RouteView.js b/modules/RouteView.js index e4a9e42..4867afc 100644 --- a/modules/RouteView.js +++ b/modules/RouteView.js @@ -6,7 +6,7 @@ import { warnOutOfSycn } from './warningUtil'; import withOnNavigate from './withOnNavigate'; import { globalStyles as styles } from './styles'; -import type { EnhancedNavigationState } from './TypeDefinition'; +import type { EnhancedNavigationRoute } from './TypeDefinition'; const { AnimatedView: NavigationTransitioner, @@ -21,8 +21,8 @@ type Props = { path: string, type: string, navigationComponent: ReactClass, - navScenes: ?Array, - _navigationState: EnhancedNavigationState, + navigationScenes: ?Array, + navigationState: EnhancedNavigationRoute, onNavigate: Function, }; @@ -32,8 +32,8 @@ class RouteView extends Component { path: PropTypes.string.isRequired, type: PropTypes.string.isRequired, navigationComponent: PropTypes.any.isRequired, - navScenes: PropTypes.arrayOf(PropTypes.element), - _navigationState: PropTypes.object, + navigationScenes: PropTypes.arrayOf(PropTypes.element), + navigationState: PropTypes.object, onNavigate: PropTypes.func.isRequired, }; @@ -44,46 +44,48 @@ class RouteView extends Component { renderScene(props: NavigationSceneRendererProps): ?ReactElement { const { scene } = props; - const { navScenes } = this.props; + const { navigationScenes } = this.props; - if (!scene.navigationState || !navScenes) { + if (!scene.route || !navigationScenes) { return null; } - const el = navScenes.find(navScene => navScene.props.path === scene.navigationState.path); + const navigationScene = navigationScenes.find( + navScene => navScene.props.path === scene.route.path + ); - if (!el) { - warnOutOfSycn('Cannot render scene', props); + if (!navigationScene) { + warnOutOfSycn('Cannot render scene', scene.route.path); } - const key = scene.navigationState.key; + const key = scene.route.key; - return React.cloneElement(el, { key, _navigationState: scene.navigationState }); + return React.cloneElement(navigationScene, { key, navigationState: scene.route }); } render(): ReactElement { const { onNavigate, - navScenes, - _navigationState, + navigationScenes, + navigationState, navigationComponent: NavigationComponent, } = this.props; const { - children, + routes, params, routeParams, location, - } = _navigationState; + } = navigationState; let wrappedChildren; - if (navScenes && children && children.length > 0) { + if (navigationScenes && routes && routes.length > 0) { // react-native/c3714d7ed7c8ee57e005d51147820456ef8cda3e // FIXME Replace `Transitioner` with `View` to reclaim performance wrappedChildren = ( diff --git a/modules/RouterContext.js b/modules/RouterContext.js index 92a2633..18922bb 100644 --- a/modules/RouterContext.js +++ b/modules/RouterContext.js @@ -18,7 +18,7 @@ import type { Snapshot, RouteDef, Location, - EnhancedNavigationState, + EnhancedNavigationRoute, ElementProvider, NavigationAction, } from './TypeDefinition'; @@ -35,7 +35,7 @@ type Props = { }; type State = { - navState: EnhancedNavigationState, + navigationState: EnhancedNavigationRoute, navigationTree: ?ReactElement, }; @@ -80,14 +80,14 @@ class RouterContext extends Component { params, nextNavigationState, }; - const navState = reducer(null, action); + const navigationState = reducer(null, action); (this: any).createElement = this.createElement.bind(this); const navigationTree = createNavigation(this.createElement, routes); - this.state = { navState, navigationTree }; - backwardHistory.push(navState); + this.state = { navigationState, navigationTree }; + backwardHistory.push(navigationState); } state: State; @@ -106,10 +106,10 @@ class RouterContext extends Component { routes, } = this.props; - const { navState } = this.state; + const { navigationState } = this.state; const activeRouteType = getActiveParentRouteType(routes); - const pop = createPop(navState); + const pop = createPop(navigationState); const transitionTo = createTransitionTo(location, activeRouteType); const push = createPush(location, activeRouteType); const replace = createReplace(location, activeRouteType); @@ -117,7 +117,7 @@ class RouterContext extends Component { // TODO User defined listenBefore // TODO Explore a better react-router API to do this const unListenBefore = listenBefore((nextLocation, callback) => { - // One-off per navState + // One-off per navigationState unListenBefore(); const path = router.createPath(nextLocation); @@ -142,7 +142,7 @@ class RouterContext extends Component { nextNavigationState, }; - const nextNavState = reducer(navState, action); + const nextNavState = reducer(navigationState, action); const activeLocation = this.shouldRedirectToActiveRoute( nextRoutes, @@ -180,7 +180,7 @@ class RouterContext extends Component { params: nextParams, } = nextProps; - let navState; + let navigationState; // TODO Refactor snapshot tracking into `nativeHistory` with our own version of // `createMemoryHistory` @@ -189,13 +189,13 @@ class RouterContext extends Component { let index = backwardHistory.findIndex(snapshot => snapshot.location.key === nextLocation.key); if (index >= 0) { // Moving backward - navState = backwardHistory[index]; + navigationState = backwardHistory[index]; const head = backwardHistory.splice(index + 1); forwardHistory = [...head, ...forwardHistory]; } else { // Assume forward index = forwardHistory.findIndex(snapshot => snapshot.location.key === nextLocation.key); - navState = forwardHistory[index]; + navigationState = forwardHistory[index]; const tail = forwardHistory.splice(0, index + 1); backwardHistory = [...backwardHistory, ...tail]; } @@ -220,19 +220,19 @@ class RouterContext extends Component { resetStack, }; - navState = reducer(this.state.navState, action); + navigationState = reducer(this.state.navigationState, action); if (nextLocation.action === HISTORY_REPLACE) { - backwardHistory[backwardHistory.length - 1] = navState; + backwardHistory[backwardHistory.length - 1] = navigationState; } else { - backwardHistory.push(navState); + backwardHistory.push(navigationState); } } const navigationTree = createNavigation(this.createElement, nextRoutes); this.setState({ - navState, + navigationState, navigationTree, }); } @@ -240,7 +240,7 @@ class RouterContext extends Component { shouldRedirectToActiveRoute( nextRoutes: Array, nextLocation: Location, - nextNavState: EnhancedNavigationState): ?Location { + nextNavState: EnhancedNavigationRoute): ?Location { const nextActiveRouteType = getActiveRouteType(nextRoutes); // Terminating at tabs if (nextActiveRouteType === TABS_ROUTE) { @@ -272,14 +272,14 @@ class RouterContext extends Component { const { location, addressBar } = this.props; const navigationTree = this.state.navigationTree; - const navState = this.state.navState; + const navigationState = this.state.navigationState; let element = null; if (navigationTree) { const props = { addressBar, navigationTree, - navState, + navigationState, location, }; diff --git a/modules/StackRoute.js b/modules/StackRoute.js index 565951f..e7174fb 100644 --- a/modules/StackRoute.js +++ b/modules/StackRoute.js @@ -7,8 +7,6 @@ import { defaultStackRouteReducer } from './ReducerUtils'; import { notImplemented, component } from './PropTypes'; import { HORIZONTAL_PAGER } from './transitionRegistry'; -const { STACK_ROUTE } = RouteTypes; - type Props = { path: string, component: ReactClass, @@ -20,6 +18,8 @@ type Props = { reducer: ?Function }; +const { STACK_ROUTE } = RouteTypes; + /* eslint-disable react/require-render-return */ class StackRoute extends Component { diff --git a/modules/StackRouteView.js b/modules/StackRouteView.js index 925058a..40ca737 100644 --- a/modules/StackRouteView.js +++ b/modules/StackRouteView.js @@ -7,7 +7,7 @@ import withOnNavigate from './withOnNavigate'; import transitionRegistry from './transitionRegistry'; import { globalStyles as styles } from './styles'; -import type { EnhancedNavigationState } from './TypeDefinition'; +import type { EnhancedNavigationRoute } from './TypeDefinition'; const { Card: NavgationCard, @@ -24,8 +24,8 @@ type Props = { type: string, navigationComponent: ReactClass, overlayComponent: ?ReactClass, - navScenes: ?Array, - _navigationState: EnhancedNavigationState, + navigationScenes: ?Array, + navigationState: EnhancedNavigationRoute, onNavigate: Function, }; @@ -36,8 +36,8 @@ class StackRouteView extends Component { type: PropTypes.string.isRequired, navigationComponent: PropTypes.any.isRequired, overlayComponent: PropTypes.any, - navScenes: PropTypes.arrayOf(PropTypes.element), - _navigationState: PropTypes.object, + navigationScenes: PropTypes.arrayOf(PropTypes.element), + navigationState: PropTypes.object, onNavigate: PropTypes.func.isRequired, }; @@ -50,19 +50,22 @@ class StackRouteView extends Component { renderOverlay(props: NavigationSceneRendererProps): ?ReactElement { const { scene } = props; - const { navScenes } = this.props; - if (!navScenes) { + const { navigationScenes } = this.props; + if (!navigationScenes) { return null; } - const el = navScenes.find(navScene => navScene.props.path === scene.navigationState.path); - if (!el) { - warnOutOfSycn('Cannot render overlay', props); + const navigationScene = navigationScenes.find( + navScene => navScene.props.path === scene.route.path + ); + + if (!navigationScene) { + warnOutOfSycn('Cannot render overlay', scene.route.path); } - const overlayComponent = el.props.overlayComponent; + const overlayComponent = navigationScene.props.overlayComponent; if (overlayComponent) { - const { location, params, routeParams } = scene.navigationState; + const { location, params, routeParams } = scene.route; return React.createElement(overlayComponent, { ...props, location, params, routeParams }); } @@ -72,12 +75,12 @@ class StackRouteView extends Component { renderScene(props: NavigationSceneRendererProps): ?ReactElement { const { scene } = props; - if (!scene.navigationState) { + if (!scene.route) { return null; } const { transition: parentTransition } = props.navigationState; - const { transition: sceneTransition } = scene.navigationState; + const { transition: sceneTransition } = scene.route; const transition = sceneTransition || parentTransition; @@ -91,7 +94,7 @@ class StackRouteView extends Component { return ( { renderCardScene(props: NavigationSceneRendererProps): ?ReactElement { const { scene } = props; - const { navScenes } = this.props; - if (!navScenes) { + const { navigationScenes } = this.props; + if (!navigationScenes) { return null; } - const el = navScenes.find(navScene => navScene.props.path === scene.navigationState.path); - if (!el) { - warnOutOfSycn('Cannot render card', props); + const navigationScene = navigationScenes.find( + navScene => navScene.props.path === scene.route.path + ); + + if (!navigationScene) { + warnOutOfSycn('Cannot render card', scene.route.path); } - return React.cloneElement(el, { _navigationState: scene.navigationState }); + return React.cloneElement(navigationScene, { navigationState: scene.route }); } render(): ReactElement { const { onNavigate, - navScenes, - _navigationState, + navigationScenes, + navigationState, navigationComponent: NavigationComponent, } = this.props; const { - children, + routes, params, routeParams, location, transition, - } = _navigationState; + } = navigationState; const { configureTransition, @@ -138,13 +144,13 @@ class StackRouteView extends Component { } = transitionRegistry[transition]; let wrappedChildren; - if (navScenes && children && children.length > 0) { + if (navigationScenes && routes && routes.length > 0) { wrappedChildren = ( , - _navigationState: EnhancedNavigationState, + navigationScenes: ?Array, + navigationState: EnhancedNavigationRoute, onNavigate: Function, }; @@ -36,8 +36,8 @@ class TabsRouteView extends Component { type: PropTypes.string.isRequired, navigationComponent: PropTypes.any.isRequired, overlayComponent: PropTypes.any, - navScenes: PropTypes.arrayOf(PropTypes.element), - _navigationState: PropTypes.object, + navigationScenes: PropTypes.arrayOf(PropTypes.element), + navigationState: PropTypes.object, onNavigate: PropTypes.func.isRequired, }; @@ -50,19 +50,22 @@ class TabsRouteView extends Component { renderOverlay(props: NavigationSceneRendererProps): ?ReactElement { const { scene } = props; - const { navScenes } = this.props; - if (!navScenes) { + const { navigationScenes } = this.props; + if (!navigationScenes) { return null; } - const el = navScenes.find(navScene => navScene.props.path === scene.navigationState.path); - if (!el) { - warnOutOfSycn('Cannot render overlay', props); + const navigationScene = navigationScenes.find( + navScene => navScene.props.path === scene.route.path + ); + + if (!navigationScene) { + warnOutOfSycn('Cannot render overlay', scene.route.path); } - const overlayComponent = el.props.overlayComponent; + const overlayComponent = navigationScene.props.overlayComponent; if (overlayComponent) { - const { location, params, routeParams } = scene.navigationState; + const { location, params, routeParams } = scene.route; return React.createElement(overlayComponent, { ...props, location, params, routeParams }); } @@ -72,12 +75,12 @@ class TabsRouteView extends Component { renderScene(props: NavigationSceneRendererProps): ?ReactElement { const { scene } = props; - if (!scene.navigationState) { + if (!scene.route) { return null; } const { transition: parentTransition } = props.navigationState; - const { transition: sceneTransition } = scene.navigationState; + const { transition: sceneTransition } = scene.route; const transition = sceneTransition || parentTransition; @@ -91,7 +94,7 @@ class TabsRouteView extends Component { return ( { renderCardScene(props: NavigationSceneRendererProps): ?ReactElement { const { scene } = props; - const { navScenes } = this.props; + const { navigationScenes } = this.props; - if (!navScenes) { + if (!navigationScenes) { return null; } - const el = navScenes.find(navScene => navScene.props.path === scene.navigationState.path); + const navigationScene = navigationScenes.find( + navScene => navScene.props.path === scene.route.path + ); - if (!el) { - warnOutOfSycn('Cannot render card', props); + if (!navigationScene) { + warnOutOfSycn('Cannot render card', scene.route.path); } - return React.cloneElement(el, { _navigationState: scene.navigationState }); + return React.cloneElement(navigationScene, { navigationState: scene.route }); } render(): ReactElement { const { onNavigate, - navScenes, - _navigationState, + navigationScenes, + navigationState, navigationComponent: NavigationComponent, } = this.props; const { - children, + routes, params, routeParams, location, transition, - } = _navigationState; + } = navigationState; const { configureTransition, @@ -140,13 +145,13 @@ class TabsRouteView extends Component { } = transitionRegistry[transition]; let wrappedChildren; - if (navScenes && children && children.length > 0) { + if (navigationScenes && routes && routes.length > 0) { wrappedChildren = ( , + routes: Array, type: string, path: string, location: Location, @@ -57,7 +57,7 @@ export type NavigationAction = { routes: Array, location: Location, params: Object, - nextNavigationState: EnhancedNavigationState, + nextNavigationState: EnhancedNavigationRoute, } -export type Snapshot = EnhancedNavigationState; +export type Snapshot = EnhancedNavigationRoute; diff --git a/modules/nativeHistory.js b/modules/nativeHistory.js index 35861e3..44392da 100644 --- a/modules/nativeHistory.js +++ b/modules/nativeHistory.js @@ -13,85 +13,85 @@ const { STACK_ROUTE } = RouteTypes; import type { Location, RouteType, + EnhancedNavigationRoute, } from './TypeDefinition'; const { PUSH: HISTORY_PUSH, REPLACE: HISTORY_REPLACE } = Actions; -const useNavState = (createHistory: Function) => - (options = {}) => { - const { - replace: baseReplace, - push: basePush, - transitionTo: baseTransitionTo, - ...history, - } = createHistory(options); - - const createPop = (navState) => (n = -1) => { - if (!n || n > -1) { - return false; - } +const useNavState = (createHistory: Function) => (options = {}) => { + const { + replace: baseReplace, + push: basePush, + transitionTo: baseTransitionTo, + ...history, + } = createHistory(options); - const prevLocation = canPopActiveStack(n, navState); + const createPop = (navigationState: EnhancedNavigationRoute) => (n = -1) => { + if (!n || n > -1) { + return false; + } - if (prevLocation) { - const stateKey = prevLocation.state.stateKey; - const location = history.createLocation(history.createPath(prevLocation), HISTORY_PUSH); - location.state = { stateKey }; + const prevLocation = canPopActiveStack(n, navigationState); - baseTransitionTo(location); - return true; - } + if (prevLocation) { + const stateKey = prevLocation.state.stateKey; + const location = history.createLocation(history.createPath(prevLocation), HISTORY_PUSH); + location.state = { stateKey }; - return false; - }; - - const createTransitionTo = (currentLocation, activeRouteType: RouteType) => (nextLocation) => { - // History API treats HISTORY_PUSH to current path like HISTORY_REPLACE to be consistent with - // browser behavior. (mjackson/history/blob/v2.0.1/modules/createHistory.js#L126) This is not - // reasonable when performing `router.pop()` on . A unique stateKey is needed - // for each `location` to (1) bust the default 'HISTORY_REPLACE' behavior, (2) location - // objects that are passed to reducer during a `pop` needs a stateKey to be able to use a - // previous state for the newly HISTORY_PUSH'ed pointer to an older scene, (3) History needs a - // unique `location.key` for each location entry. So cannot be used as stateKey. - const nLocation = nextLocation; - const stateKey = history.createKey(); - nLocation.state = { ...nLocation.state, stateKey }; - - if (nLocation.action === HISTORY_PUSH) { - const currentPath = history.createPath(currentLocation); - const nextPath = history.createPath(nLocation); - const currentStateKey = currentLocation.state.stateKey; - const nextStateKey = nLocation.state.stateKey; - - if (currentPath === nextPath && currentStateKey !== nextStateKey) { - if (activeRouteType !== STACK_ROUTE) { - nLocation.action = HISTORY_REPLACE; - } + baseTransitionTo(location); + return true; + } + + return false; + }; + + const createTransitionTo = (currentLocation, activeRouteType: RouteType) => (nextLocation) => { + // History API treats HISTORY_PUSH to current path like HISTORY_REPLACE to be consistent with + // browser behavior. (mjackson/history/blob/v2.0.1/modules/createHistory.js#L126) This is not + // reasonable when performing `router.pop()` on . A unique stateKey is needed + // for each `location` to (1) bust the default 'HISTORY_REPLACE' behavior, (2) location + // objects that are passed to reducer during a `pop` needs a stateKey to be able to use a + // previous state for the newly HISTORY_PUSH'ed pointer to an older scene, (3) History needs a + // unique `location.key` for each location entry. So cannot be used as stateKey. + const nLocation = nextLocation; + const stateKey = history.createKey(); + nLocation.state = { ...nLocation.state, stateKey }; + + if (nLocation.action === HISTORY_PUSH) { + const currentPath = history.createPath(currentLocation); + const nextPath = history.createPath(nLocation); + const currentStateKey = currentLocation.state.stateKey; + const nextStateKey = nLocation.state.stateKey; + + if (currentPath === nextPath && currentStateKey !== nextStateKey) { + if (activeRouteType !== STACK_ROUTE) { + nLocation.action = HISTORY_REPLACE; } } + } + + baseTransitionTo(nLocation); + }; - baseTransitionTo(nLocation); - }; - - const createPush = (currentLocation: Location, activeRouteType: RouteType) => (input) => - createTransitionTo(currentLocation, - activeRouteType)(history.createLocation(input, HISTORY_PUSH)); - - const createReplace = (currentLocation: Location, activeRouteType: RouteType) => (input) => - createTransitionTo(currentLocation, - activeRouteType)(history.createLocation(input, HISTORY_REPLACE)); - - return { - ...history, - baseTransitionTo, - basePush, - baseReplace, - createTransitionTo, - createPop, - createPush, - createReplace, - }; + const createPush = (currentLocation: Location, activeRouteType: RouteType) => (input) => + createTransitionTo(currentLocation, + activeRouteType)(history.createLocation(input, HISTORY_PUSH)); + + const createReplace = (currentLocation: Location, activeRouteType: RouteType) => (input) => + createTransitionTo(currentLocation, + activeRouteType)(history.createLocation(input, HISTORY_REPLACE)); + + return { + ...history, + baseTransitionTo, + basePush, + baseReplace, + createTransitionTo, + createPop, + createPush, + createReplace, }; +}; const stateKey = createRandomKey(DEFAULT_KEY_LENGTH); const rootEntry = { pathname: '/', state: { stateKey } }; diff --git a/modules/transitionRegistry.js b/modules/transitionRegistry.js index 6798d1b..054c903 100644 --- a/modules/transitionRegistry.js +++ b/modules/transitionRegistry.js @@ -1,7 +1,7 @@ import { /* NavigationExperimental, */ Animated, Easing } from 'react-native'; import invariant from 'invariant'; -import type { EnhancedNavigationState, AnimatedValue } from './TypeDefinition'; +import type { EnhancedNavigationRoute, AnimatedValue } from './TypeDefinition'; /* eslint-disable no-multi-str */ import NavigationCardStackStyleInterpolator from 'react-native/Libraries/\ @@ -58,21 +58,21 @@ function configureSkipTransition() { // deprecated function skipAnimation( // eslint-disable-line no-unused-vars position: AnimatedValue, - navigationState: EnhancedNavigationState, + navigationRoute: EnhancedNavigationRoute, ): void { - position.setValue(navigationState.index); + position.setValue(navigationRoute.index); } // deprecated function applyDefaultAnimation( // eslint-disable-line no-unused-vars position: AnimatedValue, - navigationState: EnhancedNavigationState, + navigationRoute: EnhancedNavigationRoute, ): void { Animated.spring( position, { bounciness: 0, - toValue: navigationState.index, + toValue: navigationRoute.index, } ).start(); } @@ -82,13 +82,13 @@ const noPanResponder = () => null; function createApplyAnimation(transitionSpec: Object) { return ( position: AnimatedValue, - navigationState: EnhancedNavigationState, + navigationRoute: EnhancedNavigationRoute, ): void => { Animated.timing( position, { ...transitionSpec, - toValue: navigationState.index, + toValue: navigationRoute.index, } ).start(); }; diff --git a/modules/warningUtil.js b/modules/warningUtil.js index 6b68641..a02c58f 100644 --- a/modules/warningUtil.js +++ b/modules/warningUtil.js @@ -1,22 +1,14 @@ import warning from 'warning'; import invariant from 'invariant'; -import { NavigationExperimental } from 'react-native'; - -const { - PropTypes: NavigationPropTypes, -} = NavigationExperimental; - -const { - SceneRenderer: NavigationSceneRendererProps, -} = NavigationPropTypes; const warned = {}; -export function warnOutOfSycn(context: string, props: NavigationSceneRendererProps) { +export function warnOutOfSycn(context: string, path: string) { invariant( false, - `react-router-native Route configuration is out of sync with router state. ${context} %s`, - props.scene.navigationState.path + 'react-router-native Route configuration is out of sync with router state. %s at `%s`.', + context, + path ); } diff --git a/package.json b/package.json index 98bf26f..3539ac4 100644 --- a/package.json +++ b/package.json @@ -53,8 +53,8 @@ "url": "https://github.com/jmurzy/react-router-native/issues" }, "peerDependencies": { - "react-native": "v0.27.0-rc", - "react-router": "^2.3.0" + "react-native": "0.28.0-rc.0", + "react-router": "3.0.0-alpha.1" }, "dependencies": { "history": "^2.0.1", @@ -72,9 +72,9 @@ "eslint-plugin-jsx-a11y": "^1.0.4", "eslint-plugin-react": "^5.0.1", "flow-bin": "^0.25.0", - "react": "15.1.0-alpha.1", - "react-native": "v0.27.0-rc", - "react-router": "^2.3.0", + "react": "^15.1.0", + "react-native": "0.28.0-rc.0", + "react-router": "3.0.0-alpha.1", "rimraf": "^2.5.2" } }