React Native Tutorial: Building iOS Apps with JavaScript

In this React Native tutorial you’ll learn how to build native iOS and Android apps based on the hugely popular React JavaScript library. By Christine Abernathy.

Leave a rating/review
Save for later
Update note: This tutorial has been updated to React Native 0.50, Xcode 9, and iOS 11 by Christine Abernathy. The previous tutorial was written by iOS Team member Tom Elliot.

In this React Native tutorial you’ll learn how to build native apps based on the hugely popular React JavaScript library.

What makes React Native different from other frameworks such as PhoneGap (Apache Cordova) or Appcelerator Titanium, that use JavaScript to create iOS apps?

  1. (Unlike PhoneGap) with React Native your code may be written in JavaScript but the app’s UI is fully native. It doesn’t have the drawbacks typically associated with a hybrid HTML5 app.
  2. Additionally (unlike Titanium), React introduces a novel, radical and highly functional approach to constructing user interfaces. Your UI is simply a function of the current app state.

React Native brings the React paradigm to mobile app development. It’s goal isn’t to write the code once and run it on any platform. The goal is to learn-once (the React way) and write-anywhere. An important distinction to make. This tutorial only covers iOS, but once you’ve learned the concepts here you could port that knowledge into creating an Android app very quickly.

If you have only ever written applications in Swift, you might not be particularly excited about the prospect of using JavaScript. However, the functional programming aspect should pique your interest!

Swift has introduced more functional ways to encode algorithms, as well as techniques that encourage transformation and immutability. However, the way in which you construct your UI is very much the same as it was when developing with Objective-C: it’s still UIKit-based and imperative.

The community has even added tools such as Expo and Create React Native App to help you quickly build React Native apps without having to touch Xcode or Android Studio!

This React Native tutorial takes you through the process of building an iOS app for searching UK property listings:

React Native tutorial finished app

Don’t worry if you’ve never written any JavaScript or used the CSS-like properties you’ll see. This tutorial will guide you through every step and provide resources where you can learn more.

Ready to get going? Read on!

Note: We also have an Android version of this tutorial that you may be interested in.

Getting Started

React Native uses Node.js, a JavaScript runtime, to build your JavaScript code. If you don’t already have Node.js installed, it’s time to get it!

First install Homebrew using the instructions on the Homebrew website. Then install Node.js by executing the following in a Terminal window:

brew install node

Next, use homebrew to install watchman, a file watcher from Facebook:

brew install watchman

This is used by React Native to figure out when your code changes and rebuild accordingly. It’s like having Xcode do a build each time you save your file.

Next use npm to install the React Native Command Line Interface (CLI) tool:

npm install -g react-native-cli

This uses the Node Package Manager to fetch the CLI tool and install it globally; npm is similar in function to CocoaPods or Carthage and is packaged with Node.js.

Navigate to the folder where you would like to develop your app and run the following in Terminal:

react-native init PropertyFinder

This uses the CLI tool to create a starter project containing everything you need to build and run a React Native app.

If you get complaints about the version of node, make sure the one installed by brew is the one in use. Run brew link --overwrite node in the terminal.

In Terminal, run:

cd PropertyFinder

In the created folders and files you will find a few items of note:

  • node_modules is a folder which contains the React Native framework
  • index.js is the entry point created by the CLI tool
  • App.js is the skeletal app created by the CLI tool
  • ios is a folder containing an Xcode project and the code required to bootstrap
    your application
  • android is a folder containing Android-related code, you won’t be touching those in this tutorial.

Open the PropertyFinder.xcodeproj in the ios folder with Xcode, then build and run. The simulator will start and display the following:

If you see build-time warnings related to updating PropertyFinder project settings, go ahead and make those updates. Ignore warnings related to the other projects.

Many of the warnings may be related to unused parameters. You may also see null pointer logic errors in the yoga library that are actually not errors.

If you encounter a compiler error indicating 'config.h' file not found in the third-party target, you may need to install Glog manually. Try these instructions.

You might also have noticed that a terminal window has popped up, displaying the following:

This is Metro Bundler, the React Native JavaScript bundler running under Node.js. You’ll find out what it does shortly.

Note: If you get an error starting up the packager, then in Terminal run: react-native start

Don’t close the terminal window; just keep it running in the background. If you do close it by mistake, simply stop and re-run the project via Xcode.

Note: You’ll be mostly writing JavaScript code for this React Native tutorial. Instead of using Xcode, I use Sublime Text, which is a cheap and versatile editor, but Atom, Brackets or any other lightweight editor will do the job.

React Native Basics

In this section, you’ll be introduced to React Native basics as you begin working on PropertyFinder.

Open App.js in your text editor of choice and take a look at the structure of the code in the file:

import React, { Component } from 'react'; // 1
import {
} from 'react-native';

const instructions ={ ... }); // 2

export default class App extends Component<{}> { ... } // 3

const styles = StyleSheet.create({ ... }); // 4

Let’s go through the code step-by-step:

  1. Imports the required modules.
  2. Sets up a platform-specific display message.
  3. Defines the component that represents the UI.
  4. Creates a style object that controls the component’s layout and appearance.

Take a closer look at this import statement:

import React, { Component } from 'react';

This uses the ECMAScript 6 (ES6) import syntax to load the react module and assign it to a variable called React. This is roughly equivalent to linking and importing libraries in Swift. It also uses what’s called a destructuring assignment to bring in the Component object. Destructuring lets you extract multiple object properties and assign them to variables using a single statement.

Note: For more information about ES6 modules I’d recommend reading this blog post by Dr. Axel Rauschmayer.

ES6 is a much nicer way to write JavaScript, supporting features like default parameters, classes, arrow functions, and destructuring assignments. Apple has supported ES6 since iOS 10, but older browsers may not be compatible with it. React Native uses a tool called Babel to automatically translate modern JavaScript into compatible legacy JavaScript where necessary.

Back to App.js, check out the class definition:

export default class App extends Component<{}> {

This defines a class which extends a React Component. The export default class modifier makes the class “public”, allowing it to be used in other files.

Open index.js and take a look at the entry point file:

import { AppRegistry } from 'react-native';
import App from './App';

AppRegistry.registerComponent('PropertyFinder', () => App);

This registers the imported component that serves as the app’s entry point.

It’s time to start building your app.

In App.js, add the following at the top of the file, just before the import statements:

'use strict';

This enables Strict Mode, which adds improved error handling and disables some less-than-ideal JavaScript language features. In simple terms, it makes JavaScript better!

Inside the App class replace render() with the following:

render() {
  return React.createElement(Text, {style: styles.description}, "Search for houses to buy!");

App extends React.Component, the basic building block of the React UI. Components contain immutable properties, mutable state variables and expose a method for rendering. Your current application is quite simple and only requires a render method.

React Native components are not UIKit classes; instead they are a lightweight equivalent. The framework takes care of transforming the tree of React components into the required native UI.

Next, replace the const styles statement with the following:

const styles = StyleSheet.create({
  description: {
    fontSize: 18,
    textAlign: 'center',
    color: '#656565',
    marginTop: 65,

This defines a single style that you’ve applied to the description text. If you’ve done any web development before, you’ll probably recognize those property names. The React Native StyleSheet class used to style the application UI is similar to the Cascading Style Sheets (CSS) used on the Web.

Then, get rid of the instructions assignment code block as you no longer need it.

Save your changes to App.js and return to the simulator. Press Cmd+R, and you’ll see your fledgling property search app starting to take shape:

First signs of the React Native tutorial app

That’s a JavaScript application running in the simulator, rendering a native UI, without a browser in sight!

Still don’t trust me? :] Verify it for yourself: within Xcode, select Debug\View Debugging\Capture View Hierarchy and take a look at the native view hierarchy. You will see no UIWebView instances anywhere! Your text is being displayed in a view called RCTText. But what is that? Back in Xcode select File\Open Quickly… and type in RCTView.h. Notice RCTView inherits directly from UIView. Neat!

Curious as to how it all works? In Xcode open AppDelegate.m and locate application:didFinishLaunchingWithOptions:. This method constructs a RCTRootView, which loads the JavaScript application from the index JavaScript file and renders the resultant view.

The Terminal window that was opened when you ran this application started a packager and server that allows your JavaScript code to be fetched, by default on port 8081. For example:


Open this URL in Safari; you’ll see the JavaScript code for your app. You can find your “Search for houses to buy!” description code embedded among the React Native framework.

When your app starts, this code is loaded and executed by the JavaScriptCore framework. In the case of your application, it loads the App component, then constructs the native UIKit view.