diff --git a/_index.html b/_index.html index 131666cf9ce..cdc8290f4ea 100644 --- a/_index.html +++ b/_index.html @@ -1,6 +1,7 @@ -React Native | Build Native Apps Using React
React Native
Build native apps using React

Native iOS Components

With React Native, you can use the standard platform components such as UITabBar and UINavigationController on iOS. This gives your app a consistent look and feel with the rest of the platform ecosystem, and keeps the quality bar high. These components are easily incorporated into your app using their React component counterparts, such as TabBarIOS and NavigatorIOS.

var React = require('react-native'); +React Native | Build Native Apps Using React
React Native
A framework for building native apps using React

Native iOS Components

With React Native, you can use the standard platform components such as UITabBar and UINavigationController on iOS. This gives your app a consistent look and feel with the rest of the platform ecosystem, and keeps the quality bar high. These components are easily incorporated into your app using their React component counterparts, such as TabBarIOS and NavigatorIOS.

var React = require('react-native'); var { TabBarIOS, NavigatorIOS } = React; -module.exports = React.createClass({ + +var App = React.createClass({ render: function() { return ( <TabBarIOS> @@ -10,9 +11,10 @@ module.exports /TabBarIOS> ); }, -});

Asynchronous

All operations between the JavaScript application code and the native platform are performed asynchronously, and the native modules can also make use of additional threads as well. This means we can decode images off of the main thread, save to disk in the background, measure text and compute layouts without blocking the UI, and more. As a result, React Native apps are naturally fluid and responsive. The communication is also fully serializable, which allows us to leverage Chrome Developer Tools to debug JS while running the app in the full app environment, in the sim or on a real device.

Touch Handling

iOS has a very powerful system called the Responder Chain to negotiate touches in complex view hierarchies which does not have a universal analog on the web. React Native implements a similar responder system and provides high level components such as TouchableHighlight that integrate properly with scroll views and other elements without any additional configutation.

var React = require('react-native'); +});

Asynchronous Execution

All operations between the JavaScript application code and the native platform are performed asynchronously, and the native modules can also make use of additional threads as well. This means we can decode images off of the main thread, save to disk in the background, measure text and compute layouts without blocking the UI, and more. As a result, React Native apps are naturally fluid and responsive. The communication is also fully serializable, which allows us to leverage Chrome Developer Tools to debug the JavaScript while running the complete app, either in the simulator or on a physical device.

Touch Handling

iOS has a very powerful system called the Responder Chain to negotiate touches in complex view hierarchies which does not have a universal analog on the web. React Native implements a similar responder system and provides high level components such as TouchableHighlight that integrate properly with scroll views and other elements without any additional configuration.

var React = require('react-native'); var { ScrollView, TouchableHighlight, Text } = React; -module.exports = React.createClass({ + +var TouchDemo = React.createClass({ render: function() { return ( <ScrollView> @@ -22,9 +24,10 @@ module.exports /ScrollView> ); }, -});

Flexbox and Styling

Laying out views should be easy, which is why we brought the flexbox layout model from the web to React Native. Flexbox makes it easy to build the most common UI layouts, such as stacked and nested boxes with margin and padding. React Native also supports common web syles, such as fontWeight, and the StyleSheet abstraction makes it easy to declare all your styles and layout right along with the components that use them and used inline.

var React = require('react-native'); +});

Flexbox and Styling

Laying out views should be easy, which is why we brought the flexbox layout model from the web to React Native. Flexbox makes it simple to build the most common UI layouts, such as stacked and nested boxes with margin and padding. React Native also supports common web syles, such as fontWeight, and the StyleSheet abstraction provides an optimized mechanism to declare all your styles and layout right along with the components that use them and apply them inline.

var React = require('react-native'); var { Image, StyleSheet, Text, View } = React; -module.exports = React.createClass({ + +var ReactNative = React.createClass({ render: function() { return ( <View style={styles.row}> @@ -50,13 +53,12 @@ module.exports : { flex: 1, justifyContent: 'center'}, title: { fontSize: 11, fontWeight: 'bold' }, subtitle: { fontSize: 10 }, -});

Polyfills

React Native is focused on changing the way view code is written. For the rest, we look to the web for universal standards and polyfill those APIs where appropriate. You can use npm to install JavaScript libraries that work on top of the functionality baked into React Native, such as XMLHttpRequest, requestAnimationFrame, and navigator.geolocation. We are working on expanding the available APIs, and are excited for the Open Source community to contribute as well.

var React = require('react-native'); +});

Polyfills

React Native is focused on changing the way view code is written. For the rest, we look to the web for universal standards and polyfill those APIs where appropriate. You can use npm to install JavaScript libraries that work on top of the functionality baked into React Native, such as XMLHttpRequest, window.requestAnimationFrame, and navigator.geolocation. We are working on expanding the available APIs, and are excited for the Open Source community to contribute as well.

var React = require('react-native'); var { Text } = React; -module.exports = React.createClass({ + +var GeoInfo = React.createClass({ getInitialState: function() { - return { - position: 'unknown', - }; + return { position: 'unknown' }; }, componentDidMount: function() { navigator.geolocation.getCurrentPosition( @@ -71,6 +73,59 @@ module.exports /Text> ); }, +});

Extensibility

It is certainly possible to create a great app using React Native without writing a single line of native code, but React Native is also designed to be easily expended with custom native views and modules - that means you can reuse anything you've already built, and can import and use your favorite native libraries. To create a simple module in iOS, create a new class that implements the RCTBridgeModule protocol, and add RCT_EXPORT to the function you want to make available in JavaScript.

// Objective-C + +#import "RCTBridgeModule.h" + +@interface MyCustomModule : NSObject <RCTBridgeModule> +@end + +@implementation MyCustomModule + +- (void)processString:(NSString *)input callback:(RCTResponseSenderBlock)callback +{ + RCT_EXPORT(); // available as NativeModules.MyCustomModule.processString + callback(@[[input stringByReplacingOccurrencesOfString:@"Goodbye" withString:@"Hello"];]]); +} +@end
// JavaScript + +var React = require('react-native'); +var { NativeModules, Text } = React; + +var Message = React.createClass({ + render: function() { + getInitialState() { + return { text: 'Goodbye World.' }; + }, + componentDidMount() { + NativeModules.MyCustomModule.processString(this.state.text, (text) => { + this.setState({text}); + }); + }, + return ( + <Text>{this.state.text}</Text> + ); + }, +});

Custom iOS views can be exposed by subclassing RCTViewManager, implementing a -(UIView *)view method, and exporting properties with the RCT_EXPORT_VIEW_PROPERTY macro. Then a simple JavaScript file connects the dots.

// Objective-C + +#import "RCTViewManager.h" + +@interface MyCustomViewManager : RCTViewManager +@end + +@implementation MyCustomViewManager + +- (UIView *)view +{ + return [[MyCustomView alloc] init]; +} + +RCT_EXPORT_VIEW_PROPERTY(myCustomProperty); +@end
// JavaScript + +module.exports = createReactIOSNativeComponentClass({ + validAttributes: { myCustomProperty: true }, + uiViewClassName: 'MyCustomView', });
© 2015 Facebook Inc.

Tutorial

Preface #

This is a tutorial that aims to get you up to speed with writing iOS apps using React Native. If you want to learn what React Native is and why Facebook built it, check out this blog post: [INSERT BLOG POST URL].

We assume you have experience writing websites with React. If not, you can learn about React here.

Setup #

React Native has a few requirements which you can find on the github page (specifically OSX, Xcode, Homebrew, node, npm, watchman, and (optionally) flow)

After installing these dependencies there are two simple commands to get a React Native project all set up for development.

  1. npm install -g react-native-cli

    react-native-cli is a command line interface that does the rest of the set up. It’s also an npm module so you can get it very easily. This will install react-native-cli so you can run it as a command in your terminal. You only need to do this once ever.

  2. react-native init AwesomeProject

    This command fetches the React Native source code, installs all of the other npm modules that it depends on, and creates a new Xcode project in AwesomeProject/AwesomeProject.xcodeproj.

Development #

You can now open this new project (AwesomeProject/AwesomeProject.xcodeproj) in Xcode and simply build and run it with cmd+R. Doing so will start a node server which enables live code reloading by packaging and serving the latest JS bundle to the simulator at runtime. From here out you can see your changes by pressing cmd+R in the simulator rather than recompiling in Xcode.

For this tutorial let’s build a simple version of the Movies app that fetches 25 movies that are in theaters and displays them in a ListView.

Hello World #

react-native init will copy Examples/SampleProject to whatever you named your project, in this case AwesomeProject. This is a simple hello world app. You can edit index.ios.js to make changes to the app and then press cmd+R in the simulator to see your changes.

Mocking data #

Before we write the code to fetch actual Rotten Tomatoes data, let's mock some data so we can get started with rendering some views right away. At Facebook we typically declare constants at the top of JS files just below the requires but feel free to add the following constant wherever you like:

var MOCKED_MOVIES_DATA = [ - {title: 'Title', year: '2015', posters: {thumbnail: 'http://resizing.flixster.com/yDGJbDZ4tOk8Wsfl2Ljt1JYgHpk=/53x81/dkpu1ddg7pbsk.cloudfront.net/movie/11/18/90/11189059_ori.jpg'}}, +React Native | Build Native Apps Using React

Tutorial

Preface #

This tutorial aims to get you up to speed with writing iOS apps using React Native.

We assume you have experience writing websites with React. If not, you can learn about it on the React website.

Setup #

React Native has a few requirements which you can find on the github page (specifically OSX, Xcode, Homebrew, node, npm, watchman, and (optionally) flow)

After installing these dependencies there are two simple commands to get a React Native project all set up for development.

  1. npm install -g react-native-cli

    react-native-cli is a command line interface that does the rest of the set up. It’s also an npm module so you can get it very easily. This will install react-native-cli so you can run it as a command in your terminal. You only need to do this once ever.

  2. react-native init AwesomeProject

    This command fetches the React Native source code, installs all of the other npm modules that it depends on, and creates a new Xcode project in AwesomeProject/AwesomeProject.xcodeproj.

Development #

You can now open this new project (AwesomeProject/AwesomeProject.xcodeproj) in Xcode and simply build and run it with cmd+R. Doing so will start a node server which enables live code reloading by packaging and serving the latest JS bundle to the simulator at runtime. From here out you can see your changes by pressing cmd+R in the simulator rather than recompiling in Xcode.

For this tutorial let’s build a simple version of the Movies app that fetches 25 movies that are in theaters and displays them in a ListView.

Hello World #

react-native init will copy Examples/SampleProject to whatever you named your project, in this case AwesomeProject. This is a simple hello world app. You can edit index.ios.js to make changes to the app and then press cmd+R in the simulator to see your changes.

Mocking data #

Before we write the code to fetch actual Rotten Tomatoes data, let's mock some data so we can get started with rendering some views right away. At Facebook we typically declare constants at the top of JS files just below the requires but feel free to add the following constant wherever you like:

var MOCKED_MOVIES_DATA = [ + {title: 'Title', year: '2015', posters: {thumbnail: 'http://i.imgur.com/UePbdph.jpg'}}, ];

Render a movie #

We're going to render the title, year, and thumbnail for the movie. Since we want to render an image, which is an Image component in React Native, add Image to the list of React requires above.

var { AppRegistry, Image, @@ -29,7 +29,12 @@ });

And lastly we need to apply this still to the Image component:

<Image source={{uri: movie.posters.thumbnail}} style={styles.thumbnail} - />

Press cmd+R and the image should now render.

Screenshot:

<img src="https://github.com/facebook/react-native/raw/master/docs/images/TutorialMock.png" alt="screenshot" width="320px" />

Add some styling #

Great, we've rendered our data, now let's make it look better. I'd like to put the text to the right of the image and make the title larger and centered within that area:

+---------------------------------+ + />

Press cmd+R and the image should now render.

+ +
+ + +

Add some styling #

Great, we've rendered our data, now let's make it look better. I'd like to put the text to the right of the image and make the title larger and centered within that area:

+---------------------------------+ |+-------++----------------------+| || || Title || || Image || || @@ -61,7 +66,11 @@ }, year: { textAlign: 'center', - },

This is pretty straightforward if you've ever seen CSS before. Make the title larger, add some space below it, and center all of the text within their parent container (rightContainer).

Go ahead and press cmd+R and you'll see the updated view.

Screenshot:

<img src="https://github.com/facebook/react-native/raw/master/docs/images/TutorialStyledMock.png" alt="screenshot" width="320px" />

Fetching real data #

Fetching data from Rotten Tomatoes's API isn't really relevant to learning React Native so feel free to breeze through this section.

Add the following constants to the top of the file (typically below the requires) to create the REQUEST_URL used to request data with.

var API_KEY = '7waqfqbprs7pajbz28mqf6vz'; + },

This is pretty straightforward if you've ever seen CSS before. Make the title larger, add some space below it, and center all of the text within their parent container (rightContainer).

Go ahead and press cmd+R and you'll see the updated view.

+ +
+ +

Fetching real data #

Fetching data from Rotten Tomatoes's API isn't really relevant to learning React Native so feel free to breeze through this section.

Add the following constants to the top of the file (typically below the requires) to create the REQUEST_URL used to request data with.

var API_KEY = '7waqfqbprs7pajbz28mqf6vz'; var API_URL = 'http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json'; var PAGE_SIZE = 25; var PARAMS = '?apikey=' + API_KEY + '&page_limit=' + PAGE_SIZE; @@ -113,7 +122,11 @@ this.state.movies is no longer null.

</View> </View> ); - },

Now press cmd+R and you should see "Loading movies..." until the response comes back, then it will render the first movie it fetched from Rotten Tomatoes.

Screenshot:

<img src="https://github.com/facebook/react-native/raw/master/docs/images/TutorialSingleFetched.png" alt="screenshot" width="320px" />

ListView #

Let’s now modify this application to render all of this data in a ListView, rather than just the first movie.

First thing's first, add the ListView require to the top of the file.

var { + },

Now press cmd+R and you should see "Loading movies..." until the response comes back, then it will render the first movie it fetched from Rotten Tomatoes.

+ +
+ +

ListView #

Let’s now modify this application to render all of this data in a ListView, rather than just the first movie.

Why is a ListView better than just rendering all of these elements or putting them in a ScrollView? Despite React being fast, rendering a possibly infinite list of elements could be slow. ListView schedules rendering of views so that you only display the ones on screen and those already rendered but off screen are removed from the hierarchy.

First thing's first, add the ListView require to the top of the file.

var { AppRegistry, Image, ListView, @@ -131,7 +144,7 @@ this.state.movies is no longer null.

renderRow={this.renderMovie} /> ); - },

You'll notice we added a dataSource that comes from this.state. We'll now store the data there and then change this.state.movies === null to this.state.loaded === true to check if data has been loaded. Here's what getInitialState looks like:

getInitialState: function() { + },

What is this dataSource thing and why do we use it? This way we can very cheaply know which rows have changed between updates.

You'll notice we added dataSource from this.state. The next step is to add an empty dataSource to getInitialState. Also, now that we're storing the data in dataSource, we should change this.state.movies to be this.state.loaded (boolean) so we aren't storing the data twice.

getInitialState: function() { return { dataSource: new ListView.DataSource({ rowHasChanged: (row1, row2) => row1 !== row2, @@ -148,7 +161,11 @@ this.state.movies is no longer null.

}); }) .done(); - },

Screenshot:

<img src="https://github.com/facebook/react-native/raw/master/docs/images/TutorialFinal.png" alt="screenshot" width="320px" />

Final source code #

/** + },

And here's the final result:

+ +
+ +

There's still some work to be done to make it a fully functional app such as adding navigation, search, infinite scroll loading, etc. Check the Movies Example to see it all working.

Final source code #

/** * Sample React Native App * https://github.com/facebook/react-native */ diff --git a/img/TutorialFinal.png b/img/TutorialFinal.png new file mode 100644 index 00000000000..72ee2a27e5f Binary files /dev/null and b/img/TutorialFinal.png differ diff --git a/img/TutorialMock.png b/img/TutorialMock.png new file mode 100644 index 00000000000..a89499209ab Binary files /dev/null and b/img/TutorialMock.png differ diff --git a/img/TutorialSingleFetched.png b/img/TutorialSingleFetched.png new file mode 100644 index 00000000000..bb8e0219d3a Binary files /dev/null and b/img/TutorialSingleFetched.png differ diff --git a/img/TutorialStyledMock.png b/img/TutorialStyledMock.png new file mode 100644 index 00000000000..1f54d3c0deb Binary files /dev/null and b/img/TutorialStyledMock.png differ diff --git a/img/chrome_breakpoint.png b/img/chrome_breakpoint.png index c5ab5f3e100..4b5f2872fac 100644 Binary files a/img/chrome_breakpoint.png and b/img/chrome_breakpoint.png differ