From d162a2d0272186079c7bbe340f51fdc5e5ae4839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Fri, 24 Jun 2016 08:09:58 -0700 Subject: [PATCH 1/3] Redirect Navigator Comparison to Navigation. --- website/package.json | 19 ++++++++++--------- website/server/server.js | 7 +++++++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/website/package.json b/website/package.json index 985b9bcf440416..e5f6528760a741 100644 --- a/website/package.json +++ b/website/package.json @@ -4,11 +4,20 @@ "gh-pages": "node publish-gh-pages.js" }, "dependencies": { + "babel-core": "^6.6.4", + "babel-plugin-external-helpers": "^6.5.0", + "babel-polyfill": "^6.6.1", + "babel-preset-react-native": "~1.6.0", + "babel-register": "^6.6.0", + "babel-types": "^6.6.4", "bluebird": "^2.9.21", "connect": "2.8.3", + "connect-redirection": "0.0.1", + "deep-assign": "^2.0.0", "esprima-fb": "15001.1001.0-dev-harmony-fb", "fs.extra": "1.3.2", "glob": "6.0.4", + "jsdoc-api": "^1.1.0", "jstransform": "11.0.3", "mkdirp": "^0.5.1", "optimist": "0.6.0", @@ -16,14 +25,6 @@ "react-docgen": "^2.9.0", "react-page-middleware": "git://github.com/facebook/react-page-middleware.git", "request": "^2.69.0", - "semver-compare": "^1.0.0", - "babel-core": "^6.6.4", - "babel-plugin-external-helpers": "^6.5.0", - "babel-polyfill": "^6.6.1", - "babel-preset-react-native": "~1.6.0", - "babel-register": "^6.6.0", - "babel-types": "^6.6.4", - "jsdoc-api": "^1.1.0", - "deep-assign": "^2.0.0" + "semver-compare": "^1.0.0" } } diff --git a/website/server/server.js b/website/server/server.js index 79e7fcede047ff..d48acc6c2b1995 100644 --- a/website/server/server.js +++ b/website/server/server.js @@ -14,6 +14,7 @@ var optimist = require('optimist'); var path = require('path'); var reactMiddleware = require('react-page-middleware'); var convert = require('./convert.js'); +var redirect = require('connect-redirection'); var argv = optimist.argv; @@ -42,7 +43,13 @@ var buildOptions = { }; var app = connect() + .use(redirect()) .use(function(req, res, next) { + // Handle redirects + if (req.url === '/react-native/docs/navigator-comparison.html') { + res.redirect('/react-native/docs/navigation.html'); + } + // convert all the md files on every request. This is not optimal // but fast enough that we don't really need to care right now. if (!server.noconvert && req.url.match(/\.html|\/$/)) { From 74922684ac0a5f5d77b107824b7ae2376a8111c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Fri, 24 Jun 2016 09:01:58 -0700 Subject: [PATCH 2/3] Remove navigator comparison, and update API references for Navigator and NavigatorIOS. --- .../Components/Navigation/NavigatorIOS.ios.js | 71 ++++++++---- .../CustomComponents/Navigator/Navigator.js | 29 +++-- docs/Navigation.md | 103 +++++++++--------- docs/NavigatorComparison.md | 49 --------- 4 files changed, 115 insertions(+), 137 deletions(-) delete mode 100644 docs/NavigatorComparison.md diff --git a/Libraries/Components/Navigation/NavigatorIOS.ios.js b/Libraries/Components/Navigation/NavigatorIOS.ios.js index 8e8390d15ceac6..b44843640c6544 100644 --- a/Libraries/Components/Navigation/NavigatorIOS.ios.js +++ b/Libraries/Components/Navigation/NavigatorIOS.ios.js @@ -93,10 +93,17 @@ type Event = Object; */ /** - * `NavigatorIOS` is a wrapper around UIKit navigation, enabling you to - * implement back-swipe functionality in your iOS app. Take a look at + * `NavigatorIOS` is a wrapper around + * [`UINavigationController`](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/), + * enabling you to implement a navigation stack. It works exactly the same as it + * would on a native app using `UINavigationController`, providing the same + * animations and behavior from UIKIt. + * + * As the name implies, it is only available on iOS. Take a look at * [`Navigator`](/docs/navigator.html) for a similar solution for your - * cross-platform needs. + * cross-platform needs, or check out + * [react-native-navigation](https://github.com/wix/react-native-navigation), a + * component that aims to provide native navigation on both iOS and Android. * * To set up the navigator, provide the `initialRoute` prop with a route * object. A route object is used to describe each scene that your app @@ -106,13 +113,13 @@ type Event = Object; * import React, { Component } from 'react'; * import { NavigatorIOS, Text } from 'react-native'; * - * class NavvyIOS extends Component { + * export default class NavigatorIOSApp extends Component { * render() { * return ( * @@ -120,39 +127,54 @@ type Event = Object; * } * } * - * class MyView extends Component { + * class MyScene extends Component { + * static propTypes = { + * title: PropTypes.string.isRequired, + * navigator: PropTypes.object.isRequired, + * } + * + * constructor(props, context) { + * super(props, context); + * this._onForward = this._onForward.bind(this); + * this._onBack = this._onBack.bind(this); + * } + * + * _onForward() { + * this.props.navigator.push({ + * title: 'Scene ' + nextIndex, + * }); + * } + * * render() { - * return( - * - * See you on the other nav! - * - * ); + * return ( + * + * Current Scene: { this.props.title } + * + * Tap me to load the next scene + * + * + * ) * } * } * ``` * - * In this code, the navigator sets its title and renders `MyView`. The - * component specified in `initialRoute` will receive a `route` prop and a - * `navigator` prop representing the navigator. + * In this code, the navigator renders the component specified in initialRoute, + * which in this case is `MyScene`. This component will receive a `route` prop + * and a `navigator` prop representing the navigator. The navigator's navigation + * bar will render the title for the current scene, "My Initial Scene". * * You can optionally pass in a `passProps` property to your `initialRoute`. * `NavigatorIOS` passes this in as props to the rendered component: * * ``` * initialRoute={{ - * component: MyView, - * title: 'Foo This', + * component: MyScene, + * title: 'My Initial Scene', * passProps: { myProp: 'foo' } * }} * ``` * - * You can then access the props passed in: - * - * ``` - * - * See you on the other nav {this.props.myProp}! - * - * ``` + * You can then access the props passed in via `{this.props.myProp}`. * * #### Handling Navigation * @@ -254,6 +276,7 @@ type Event = Object; * * In the example above the navigation bar color is changed when the new route * is pushed. + * */ var NavigatorIOS = React.createClass({ diff --git a/Libraries/CustomComponents/Navigator/Navigator.js b/Libraries/CustomComponents/Navigator/Navigator.js index f09f6488a44baf..63b53b03f20fac 100644 --- a/Libraries/CustomComponents/Navigator/Navigator.js +++ b/Libraries/CustomComponents/Navigator/Navigator.js @@ -130,9 +130,10 @@ var GESTURE_ACTIONS = [ /** * `Navigator` handles the transition between different scenes in your app. - * You should consider using this component instead of `NavigatorIOS` if you're - * building a cross-platform app. `Navigator` is implemented in JavaScript - * whereas `NavigatorIOS` is a wrapper around `UINavigationController`. + * It is implemented in JavaScript and is available on both iOS and Android. If + * you are targeting iOS only, you may also want to consider using + * [`NavigatorIOS`](docs/navigatorios.html) as it leverages native UIKit + * navigation. * * To set up the `Navigator` you provide one or more objects called routes, * to identify each scene. You also provide a `renderScene` function that @@ -142,13 +143,13 @@ var GESTURE_ACTIONS = [ * import React, { Component } from 'react'; * import { Text, Navigator } from 'react-native'; * - * class NavAllDay extends Component { + * export default class NavAllDay extends Component { * render() { * return ( * - * Hello {route.name}! + * Hello {route.title}! * } * style={{padding: 100}} * /> @@ -158,8 +159,8 @@ var GESTURE_ACTIONS = [ * ``` * * In the above example, `initialRoute` is used to specify the first route. It - * contains a `name` property that identifies the route. The `renderScene` - * prop returns a function that displays text based on the route's name. + * contains a `title` property that identifies the route. The `renderScene` + * prop returns a function that displays text based on the route's title. * * ### Additional Scenes * @@ -169,8 +170,8 @@ var GESTURE_ACTIONS = [ * ``` * render() { * const routes = [ - * {name: 'First Scene', index: 0}, - * {name: 'Second Scene', index: 1}, + * {title: 'First Scene', index: 0}, + * {title: 'Second Scene', index: 1}, * ]; * return ( * - * Hello {route.name}! + * Hello {route.title}! * * } * style={{padding: 100}} @@ -256,6 +257,12 @@ var GESTURE_ACTIONS = [ * This sets up a left navigator bar button that's visible on scenes after the * the first one. When the button is tapped the navigator is popped. * + * Another type of navigation bar, with breadcrumbs, is provided by + * `Navigator.BreadcrumbNavigationBar`. You can also provide your own navigation + * bar by passing it through the `navigationBar` prop. See the + * [UIExplorer](https://github.com/facebook/react-native/tree/master/Examples/UIExplorer) + * demo to try out both built-in navigation bars out and see how to use them. + * * ### Scene Transitions * * To change the animation or gesture properties of the scene, provide a diff --git a/docs/Navigation.md b/docs/Navigation.md index f4a8fcab9880d1..c90c6c0e34b910 100644 --- a/docs/Navigation.md +++ b/docs/Navigation.md @@ -4,22 +4,22 @@ title: Navigation layout: docs category: Guides permalink: docs/navigation.html -next: navigator-comparison +next: performance --- Mobile apps rarely consist of just one screen or scene. As soon as you add a second scene to your app, you will have to take into consideration how the user will navigate from one scene to the other. -Navigators in React Native allow you to push and pop scenes in a master/detail stack, or to pop up modal scenes. Navigators handle the transitions between scenes, and also maintain the navigational state of your application. +Navigators in React Native allow you to push and pop scenes in a master/detail stack, or to pop up modal scenes. Navigators handle the transition between scenes, and also maintain the navigational state of your application. -If you are just getting started with React Native, you will probably want to start with the `Navigator` component. +If you are new to React Native, you will probably want to start with the Navigator component. ## Navigator -`Navigator` is a cross-platform implementation of a navigation stack, so it works on both iOS and Android. It is easy to customize and includes simple navigation bars. +[Navigator](docs/navigator.html) is a cross-platform implementation of a navigation stack, so it works on both iOS and Android. It is easy to customize and includes simple navigation bars. ```js { // We'll get to this function soon. }} @@ -31,28 +31,10 @@ Something you will encounter a lot when dealing with navigation is the concept o The `push` and `pop` functions provided by Navigator can be used to push and pop routes into the navigation stack. A more complete example that demonstrates the pushing and popping of routes could therefore look something like this: ```js -class MyScene extends Component { - static propTypes = { - title: PropTypes.string.isRequired, - onForward: PropTypes.func.isRequired, - onBack: PropTypes.func.isRequired, - } - render() { - return ( - - Current Scene: { this.props.title } - - Tap me to load the next scene - - - Tap me to go back - - - ) - } -} +import React, { Component, PropTypes } from 'react'; +import { Navigator, Text, TouchableHighlight, View } from 'react-native'; -class SimpleNavigationApp extends Component { +export default class SimpleNavigationApp extends Component { render() { return ( + Current Scene: { this.props.title } + + Tap me to load the next scene + + + Tap me to go back + + + ) + } +} ``` In this example, the `MyScene` component is passed the title of the current route via the `title` prop. It displays two tappable components that call the `onForward` and `onBack` functions passed through its props, which in turn will call `navigator.push()` and `navigator.pop()` as needed. @@ -86,7 +89,7 @@ While this is a very basic example, it can easily be adapted to render an entire ## NavigatorIOS -If you are targeting iOS only, you may also want to consider using `NavigatorIOS`. It looks and feels just like `UINavigationController`, because it is actually built on top of it. +If you are targeting iOS only, you may also want to consider using [NavigatorIOS](docs/navigatorios.html). It looks and feels just like [`UINavigationController`](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/), because it is actually built on top of it. ```js ``` -Just like Navigator, it it uses routes to represent scenes, with some important differences. The actual component that will be rendered can be specified using the `component` key in the route, and any props that should be passed to this component can be specified in `passProps`. A navigator object is automatically passed as a prop to the component, allowing you to call `push` and `pop` as needed. +Just like Navigator, NavigatorIOS uses routes to represent scenes, with some important differences. The actual component that will be rendered can be specified using the `component` key in the route, and any props that should be passed to this component can be specified in `passProps`. A "navigator" object is automatically passed as a prop to the component, allowing you to call `push` and `pop` as needed. + +As NavigatorIOS leverages native UIKit navigation, it will automatically render a navigation bar with a back button and title. Check out the [NavigatorIOS reference docs](docs/navigatorios.html) to learn more about this component. ```js +import React, { Component, PropTypes } from 'react'; +import { NavigatorIOS, Text, TouchableHighlight, View } from 'react-native'; + +export default class NavigatorIOSApp extends Component { + render() { + return ( + + ) + } +} + class MyScene extends Component { static propTypes = { title: PropTypes.string.isRequired, @@ -112,7 +134,6 @@ class MyScene extends Component { constructor(props, context) { super(props, context); this._onForward = this._onForward.bind(this); - this._onBack = this._onBack.bind(this); } _onForward() { @@ -121,10 +142,6 @@ class MyScene extends Component { }); } - _onBack() { - this.props.navigator.pop(); - } - render() { return ( @@ -132,30 +149,10 @@ class MyScene extends Component { Tap me to load the next scene - - Tap me to go back - ) } } - -class NavigatorIOSApp extends Component { - render() { - return ( - - - } - /> - ) - } -} ``` > You may also want to check out [react-native-navigation](https://github.com/wix/react-native-navigation), a component that aims to provide native navigation on both iOS and Android. diff --git a/docs/NavigatorComparison.md b/docs/NavigatorComparison.md deleted file mode 100644 index a6ab1c904dd31b..00000000000000 --- a/docs/NavigatorComparison.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: navigator-comparison -title: Navigator Comparison -layout: docs -category: Guides -permalink: docs/navigator-comparison.html -next: performance ---- - -The differences between [Navigator](docs/navigator.html) -and [NavigatorIOS](docs/navigatorios.html) are a common -source of confusion for newcomers. - -Both `Navigator` and `NavigatorIOS` are components that allow you to -manage the navigation in your app between various "scenes" (another word -for screens). They manage a route stack and allow you to pop, push, and -replace states. In this way, [they are similar to the html5 history -API](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history). -The primary distinction between the two is that `NavigatorIOS` leverages -the iOS -[UINavigationController](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/) -class, and `Navigator` re-implements that functionality entirely in -JavaScript as a React component. A corollary of this is that `Navigator` -will be compatible with Android and iOS, whereas `NavigatorIOS` will -only work on the one platform. Below is an itemized list of differences -between the two. - -## Navigator - -- Extensive API makes it completely customizable from JavaScript. -- Under active development from the React Native team. -- Written in JavaScript. -- Works on iOS and Android. -- Includes a simple navigation bar component similar to the default `NavigatorIOS` bar: `Navigator.NavigationBar`, and another with breadcrumbs called `Navigator.BreadcrumbNavigationBar`. See the UIExplorer demo to try them out and see how to use them. - - Currently animations are good and improving, but they are still less refined than Apple's, which you get from `NavigatorIOS`. -- You can provide your own navigation bar by passing it through the `navigationBar` prop. - -## NavigatorIOS - -- Small, limited API makes it much less customizable than `Navigator` in its current form. -- Development belongs to open-source community - not used by the React Native team on their apps. - - A result of this is that there is currently a backlog of unresolved bugs, nobody who uses this has stepped up to take ownership for it yet. - - You may find an alternative in the community project [react-native-navigation](https://github.com/wix/react-native-navigation) which replaces `NavigatorIOS`. -- Wraps UIKit, so it works exactly the same as it would on another native app. Lives in Objective-C and JavaScript. - - Consequently, you get the animations and behavior that Apple has developed. -- iOS only. -- Includes a navigation bar by default; this navigation bar is not a React Native view component and the style can only be slightly modified. - -For most non-trivial apps, you will want to use `Navigator` - it won't be long before you run into issues when trying to do anything complex with `NavigatorIOS`. From 02bb51177b08bb4bff9772029a5840b1dd17e82f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ramos?= Date: Fri, 24 Jun 2016 09:25:59 -0700 Subject: [PATCH 3/3] Revert navigation redirect. --- docs/JavaScriptEnvironment.md | 2 +- ...{Navigation.md => Navigator-Comparison.md} | 4 ++-- website/package.json | 19 +++++++++---------- website/server/server.js | 7 ------- 4 files changed, 12 insertions(+), 20 deletions(-) rename docs/{Navigation.md => Navigator-Comparison.md} (98%) diff --git a/docs/JavaScriptEnvironment.md b/docs/JavaScriptEnvironment.md index 857a3fd71a7de9..4e2e3c1f21d579 100644 --- a/docs/JavaScriptEnvironment.md +++ b/docs/JavaScriptEnvironment.md @@ -4,7 +4,7 @@ title: JavaScript Environment layout: docs category: Guides permalink: docs/javascript-environment.html -next: navigation +next: navigator-comparison --- ## JavaScript Runtime diff --git a/docs/Navigation.md b/docs/Navigator-Comparison.md similarity index 98% rename from docs/Navigation.md rename to docs/Navigator-Comparison.md index c90c6c0e34b910..efbcef3f4a24a1 100644 --- a/docs/Navigation.md +++ b/docs/Navigator-Comparison.md @@ -1,9 +1,9 @@ --- -id: navigation +id: navigator-comparison title: Navigation layout: docs category: Guides -permalink: docs/navigation.html +permalink: docs/navigator-comparison.html next: performance --- diff --git a/website/package.json b/website/package.json index e5f6528760a741..985b9bcf440416 100644 --- a/website/package.json +++ b/website/package.json @@ -4,20 +4,11 @@ "gh-pages": "node publish-gh-pages.js" }, "dependencies": { - "babel-core": "^6.6.4", - "babel-plugin-external-helpers": "^6.5.0", - "babel-polyfill": "^6.6.1", - "babel-preset-react-native": "~1.6.0", - "babel-register": "^6.6.0", - "babel-types": "^6.6.4", "bluebird": "^2.9.21", "connect": "2.8.3", - "connect-redirection": "0.0.1", - "deep-assign": "^2.0.0", "esprima-fb": "15001.1001.0-dev-harmony-fb", "fs.extra": "1.3.2", "glob": "6.0.4", - "jsdoc-api": "^1.1.0", "jstransform": "11.0.3", "mkdirp": "^0.5.1", "optimist": "0.6.0", @@ -25,6 +16,14 @@ "react-docgen": "^2.9.0", "react-page-middleware": "git://github.com/facebook/react-page-middleware.git", "request": "^2.69.0", - "semver-compare": "^1.0.0" + "semver-compare": "^1.0.0", + "babel-core": "^6.6.4", + "babel-plugin-external-helpers": "^6.5.0", + "babel-polyfill": "^6.6.1", + "babel-preset-react-native": "~1.6.0", + "babel-register": "^6.6.0", + "babel-types": "^6.6.4", + "jsdoc-api": "^1.1.0", + "deep-assign": "^2.0.0" } } diff --git a/website/server/server.js b/website/server/server.js index d48acc6c2b1995..79e7fcede047ff 100644 --- a/website/server/server.js +++ b/website/server/server.js @@ -14,7 +14,6 @@ var optimist = require('optimist'); var path = require('path'); var reactMiddleware = require('react-page-middleware'); var convert = require('./convert.js'); -var redirect = require('connect-redirection'); var argv = optimist.argv; @@ -43,13 +42,7 @@ var buildOptions = { }; var app = connect() - .use(redirect()) .use(function(req, res, next) { - // Handle redirects - if (req.url === '/react-native/docs/navigator-comparison.html') { - res.redirect('/react-native/docs/navigation.html'); - } - // convert all the md files on every request. This is not optimal // but fast enough that we don't really need to care right now. if (!server.noconvert && req.url.match(/\.html|\/$/)) {