Hello World and the React Native CLI

First, navigate into the folder where you want to have your project. Mine is /Users/azat/Documents/Code/react/ch9/. Then run the $ react-native init terminal command to initiate the project by creating iOS and Android projects, package.json, and other files and folders:

1 $ react-native init hello

Wait. It might take some time. There are a few things happening at this moment. Obviously, the folder hello is created. Then, the tool creates package.json. (I love how Node and npm are everywhere nowadays. This wasn’t the case in 2012!) In package.json, the react-native CLI, which is global, puts a local dependency, react-native. This is similar to running $ npm i react-native --save.

After that step, the global react-native CLI runs the local code from the hello/node_modules/react-native/local-cli/cli.js file, and that in turn runs the helper bash script hello/node_modules/react-native/init.sh. That bash script creates scaffolding with React Native code in the index.ios.js and index.android.js files as well as iOS and Android projects in the ios and android folders.

In the ios folder, the tool creates Xcode project files with Objective C code. That’s our focus right now. Here’s the boilerplate folder structure created by the tool:

 1 /android
 2   /app
 3   /gradle
 4   - build.gradle
 5   - gradle.properties
 6   - gradlew
 7   - gradlew.bat
 8   - settings.gradle
 9 /ios
10   /hello
11   /hello.xcodeproj
12   /helloTests
13 /node_modules
14   - ...
15 - index.android.js
16 - index.ios.js
17 - package.json
18 - .watchman.config
19 - .flowconfig

Once everything is generated, you’ll be returned to the command prompt. The output on my computer was this, which even tells me how to start the apps:

1 To run your app on iOS:
2    Open /Users/azat/Documents/Code/react/ch9/hello/ios/hello.xcodeproj in Xcode
3    Hit the Run button
4 To run your app on Android:
5    Have an Android emulator running (quickest way to get started), or a device c\
6 onnected
7    cd /Users/azat/Documents/Code/react/ch9/hello
8    react-native run-android

You have two options. You can manually open Xcode and select Open (Command+O) from the File menu, open the hello.xcodeproj file, and click the black rectangle to build and run. Or you can navigate into the folder with $ cd hello, run $ open ios/hello.xcodeproj, and click on “play” in Xcode to build and run.

If you followed the steps correctly, you will see a new terminal window that says React Packager. It starts with a message:

 1  ~/Documents/Code/react/ch9/hello/node_modules/react-native/packager ~
 2  ┌────────────────────────────────────────────────────────────────────────────┐
 3  │  Running packager on port 8081.                                            │
 4  │                                                                            │
 5  │  Keep this packager running while developing on any JS projects. Feel      │
 6  │  free to close this tab and run your own packager instance if you          │
 7  │  prefer.                                                                   │
 8  │                                                                            │
 9  │  https://github.com/facebook/react-native                                  │
10  │                                                                            │
11  └────────────────────────────────────────────────────────────────────────────┘
12 Looking for JS files in
13    /Users/azat/Documents/Code/react/ch9/hello
14 
15 [12:15:42 PM] <START> Building Dependency Graph
16 [12:15:42 PM] <START> Crawling File System
17 [12:15:42 PM] <START> Loading bundles layout
18 [12:15:42 PM] <END>   Loading bundles layout (0ms)

So what is happening here? React Native packages our React Native JavaScript files and serves them on localhost:8081. That’s right, it’s just like any other web server if you open your browser at http://localhost:8081/index.ios.bundle?platform=ios&dev=true. Open it in your browser now. Search for “hello”. You will see the React Native code bundled up together in one big file. This should sound familiar to most web developers. ;-)

Where did I get the http://localhost:8081/index.ios.bundle?platform=ios&dev=true URL? It’s in the hello/ios/hello/AppDelegate.m file, on line 34 (you are using the same version as me, right?):

1 jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?p\
2 latform=ios&dev=true"];

The Objective C code grabs the JavaScript from the server. That’s default option number one. There’s a second option, which is commented at the moment. It takes the JavaScript code from the static file (line 42 in the same file). It’s good to have options!

The comments tell us how we can spin up the server. It’s just the $ npm start command, which runs $ react-native start, so we can use the latter too. So if you are switching between projects or you don’t want to use the terminal process opened automatically by Xcode, you can always start a new server. Just keep in mind, as with any server, that you cannot have two of them listening on the same port. Therefore, terminate the old process before spinning up a new server on localhost:8081.

It takes some time to launch the Simulator window. I prefer working with iPhone 6, not iPhone 6 Plus. This way I have more space for development on my screen. By now you should have the Simulator window opened. Poke around. There’s not much to see, as shown in figure 1.

Go ahead and open the index.io.js file. You can see the familiar-looking JavaScript/Node code. If you’re not comfortable with ES6 yet (or ES2015—its official name), take a look at chapter 10 and appendix I.

At the beginning of the file, there’s a destructuring statement to import objects from React Native:

1 var React = require('react-native');
2 var {
3   AppRegistry,
4   StyleSheet,
5   Text,
6   View,
7 } = React;

Next, you can see your good old friend React.createClass() with the render method:

 1 var hello = React.createClass({
 2 	render: function() {
 3 		return (
 4 			<View style={styles.container}>
 5         		<Text style={styles.welcome}>
 6 		          Welcome to React Native!
 7 		        </Text>
 8 	    	    <Text style={styles.instructions}>
 9 	        	  To get started, edit index.ios.js
10 		        </Text>
11 		        <Text style={styles.instructions}>
12 					Press Cmd+R to reload,{'\n'} Cmd+D or shake for dev menu
13 	        	</Text>
14 		     </View>
15 		);
16 	}
17 });

Gosh, with good comments like this I’ll soon be out of business—meaning I won’t need to write books. ;-) As they say, pressing Command+R in the Simulator will reload it. Go ahead and change “Welcome to React Native!” to “Hello World!” Save index.ios.js, and reload the app in the Simulator window.

Note: If you are using some nonstandard keyboard layout like Dvorak or Colemak (as I do), in the Simulator window you will have to use the standard US layout for the shortcuts, and for typing text as well.

Observe the changes and notice how we didn’t have to rebuild the Xcode project. Watchman updated the package after we saved the file. The new code was served on the server at localhost:8081. You can see the text “Hello World!” in the browser if you go to http://localhost:8081/index.ios.bundle?platform=ios&dev=true. Once we reloaded the Simulator, the new code was there!

There are two more interesting things in index.ios.js (and then we’ll move on to exploring each component individually): StyleSheet and AppRegistry. They are not in web React, so let me explain them.