Menu Search
Jump to the content X X
Smashing Conf New York

You know, we use ad-blockers as well. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. our upcoming SmashingConf New York, dedicated to smart front-end techniques and design patterns.

React Native Tutorial – Building Your First iOS App With JavaScript (Part 1)

The idea of building mobile apps with JavaScript is not new. We’ve seen frameworks like Ionic1 and PhoneGap2 take on the challenge, and to some extent succeed in gaining a fair amount of developer and community support. To part 23 of the tutorial.

These frameworks and the whole idea of building mobile apps with JavaScript4 never appealed to me, though. I always thought, why not just learn Swift/Objective-C or Java and build real apps? That definitely requires a significant amount of learning, but isn’t that what we developers do and should be good at? Quickly learn new languages and frameworks? What’s the point, then? For me, the advantages never outweighed the doubts.

Until I read this article from Chalk + Chisel5, the following line in particular:

Fast-forward a couple of months, and I’m confident enough to say I may never write an iOS app in Objective-C or Swift again.

What? Are you, like… serious?

Further Reading on SmashingMag: Link

Reading such a bold assertion made me go ahead and give React Native a shot. Why not? I was already using React and loving it. React Native is so similar to React (duh!), you’ll feel right at home if you’re already a React developer. Even if you’re not, React luckily happens to be very easy to wrap your head around.

What We Will Be Building Link

I’ve never had luck finding the perfect wallpaper app for my iPhone in the App store. On the desktop, Unsplash10 is the one-stop shop for all my wallpaper needs. On the phone: Settings → Wallpaper :(

So, unlike some other tutorials where you build counters and barely use them, in this tutorial, together we’ll build ourselves an app that will pull random stunning wallpapers from Unsplash, display them in an aesthetically pleasing way, and allow you to save wallpapers of your choice to the Camera Roll. Believe me, I have found myself using this app more than I initially thought. Even if by the end of this tutorial React Native fails to impress you, you’ll still end up having a really cool wallpaper app. Isn’t that great?

Before we start, here are some things you should be familiar with:

  1. JavaScript
  2. Some ES201511 features, namely Classes12, Arrow Functions13, Destructuring14 and Template Strings15
  3. Mac OS X Terminal
  4. CSS (yup!)
  5. React16 (optional)

One more thing. As the title clearly states, in this tutorial we’ll be building an iOS app. Which requires, yes, even with React Native, that you’re on a Mac. With React Native you can definitely build Android apps on Windows and Linux17 but not iOS ones. Therefore, from here on in, this tutorial assumes you’re running Mac OS X.

Takeaways Link

By the end of this tutorial, you’ll be familiar enough with React Native to start writing your own apps right away. We’ll go over setting up a project in Xcode, installing third party modules and components, linking libraries, styling with flexbox, creating a custom gesture listener, and many other things.

If you haven’t used React before, this tutorial will also set you up with React. React is the new hot JS library with a lot of potential, and I don’t see it going anywhere in near future.

This tutorial has been divided into two parts for your convenience. Each part has five sections. In each section we accomplish a goal that takes us a step closer to finishing our app. I’d advise that once started you should finish that whole section in one go since they are short, and in that way you’ll get to know the whole concept I am trying to introduce without breaking your flow.

For your reference, the final code for the app we’re building can be found in this GitHub repo18.

1. Setting Up A Blank React Native Project Link

Make sure you have Xcode 7.019 or higher installed. it can be downloaded free from the App Store.

Chances are (if you’re a web developer and reading this in 2016) you already have Node installed. But if that’s not the case, go ahead and install Node20 too. Another important tool we’ll need is npm21. Node comes with npm installed; you’ll need to update it, however, as it gets updated rather frequently. Follow this installation guide22.

That’s all we’ll need. Now, from the terminal run npm install -g react-native-cli. This will install React Native globally on your system.

If everything seems way too new to you, or you’re just feeling a little lost in the whole installation process, the official getting started guide23 is always there to help you out.

Find a good location on your computer where you would like to set up the project. Once there, from the terminal run react-native init SplashWalls.

This should fetch and install all the required modules and create a new folder called SplashWalls.

react native tutorial24

Contents of SplashWalls folder.

One great thing about React Native is you can write both Android and iOS applications together with a majority of JavaScript code shared between them. Inside the newly created folder you will find two .js files: index.android.js and index.ios.js – the names are self-explanatory. If you’re building an iOS app you’ll work with index.ios.js; with index.android.js for an Android app; and both for, you know, both platforms.

Since we’re building an iOS app, for the sake of this tutorial and to keep things clean we will get rid of the index.android.js and the android folder altogether. index.ios.js is the file we’ll be working with. This is the file that is first executed when the app launches.

Next, head on over to the ios folder and fire up SplashWalls.xcodeproj.

You should see a Xcode window pop up like one shown below.

Xcode on first launch.25

Xcode on first launch.

Notice the warning in the image above that says “No matching provisioning profiles found.” Let’s fix this.

First, change the text in the field Bundle Identifier to something custom. You need to make sure that whatever you enter follows reverse DNS convention26, in which the domain name of your organization is reversed and suffixed with further identifiers. This convention helps distinguish your application from others on a device and on the App Store. I will use com.nashvail.me.tutorial.SplashWalls; simply substitute your name in place of mine if you can’t seem to make something up.

Next, choose your name from the team dropdown.

Choose a team name.27

Choose a team name.

Click on Fix Issue.

While we’re at it, notice the Deployment Info section. It has some default settings applied.

Initial Deployment info settings.28

Initial deployment info settings.

Change the settings to match the following:

Final deployment info settings.29

Final deployment info settings.

We’ll make the app portrait-only and hide the status bar as well.

Go ahead and hit the Run button at the top-left in Xcode. Doing so will launch a terminal window like one shown below. Initial transformation takes a bit of time.

Terminal window on first run.30

Terminal window on first run.

Once done, you should see the following output in the simulator:

Simulator on first launch.31

Simulator on first launch.

And with this we’ve completed our very first section.

2. Fetching Wallpaper Data From The API Link

In this section we will make calls to the Unsplash.it32 API asking for wallpaper data. But before we start doing all the interesting work, there is some set-up to be done.

Switching To ES2015 Class Syntax Link

On opening the index.ios.js file you’ll notice some initial code already present. This is the code responsible for the output in the simulator (previous image).

Inside index.ios.js notice the line of code that says var SplashWalls = React.createClass({ ... }). We are going to modify this. We will use ES2015’s class syntax for this tutorial.

We developers are curious souls. I know you must be asking, Why? Why switch to the class syntax?

It all comes down to personal preference. I have programmed extensively in object-oriented languages before and class just feels more familiar to me. Moreover, by using class you also choose to keep the code a little cleaner as you don’t have to add commas after each method declaration.

On the flip side, when you choose class you don’t get features like autobinding or access to the isMounted method, which is not a bad thing at all, as you’re not really going to find yourself at a loss by not using these.

Whichever way you go, you’re creating a class after all. My advice would be to use class. It’s a new feature and sooner or later you’ll find yourself using ES2015. And if you’re following this tutorial, you will have to use class – you don’t really have a choice!

For more on this consider reading “React.Component vs React.createClass33” by Naman Goel and Zach Silveira.

Once you’ve made the necessary changes, the block of code should now be as shown:

class SplashWalls extends Component{
  render() {
    return (
      
  . <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.ios.js
        </Text>
        <Text style={styles.instructions}>
          Press Cmd+R to reload,{'\n'}
          Cmd+D or shake for dev menu
        </Text>
       
   .</View>
    );
  }
};

For folks new to React, the code inside return parens may seem a little wacky, but it’s not rocket science, just good old XML-like syntax called JSX. Read more about it here34.

Compared with the pre-class implementation, the var syntax is gone. Also render: function(){… is now just render(){….

Hey! But what is that Component you are extending? And you’d be right to ask. If you ran the project in Xcode now, you’d get an error saying Component is not defined. You can do two things here: replace Component with React.Component; or add a new line inside the block (shown below) at the top of the file.

In this and later code examples, I surround the newly added lines with /***/ so that it’s easier for you to compare the code you’re writing with what is shown here. Just make sure that if you copy code from the samples you don’t end up copying /***/ along with the actual code. Since JSX doesn’t support /***/ comments, you will end up crashing the app if you included these in your JSX code.

var {
  AppRegistry,
  StyleSheet,
  Tex .t,
  View,
  /***/
  Component 
  /***/
} = React;

All the block of code above does is save you a couple of keystrokes. For example, if you didn’t include these lines of code at the top, you’d have to write React.AppRegistry instead of just AppRegistry every time you wanted to do so. Pretty frigging cool! Isn’t it? OK, not so much.

Go back to Xcode and run the project once again to make sure you didn’t break anything in the process.

Everything good? Great! Let’s move on.

Inside the SplashWalls class, the first thing we need to do is add a constructor. Inside the constructor we will initialize our state variables. The only two state variables we will need at this point are an array – wallsJSON – which is going to store all the JSON data fetched from the API, and isLoading, which is a Boolean variable, meaning it will hold a value of either true or false. Having this state variable will help us show and hide the loading screen depending on whether the data has been loaded or not.

Inside the SplashWalls class, add the constructor as shown below.

class SplashWalls extends Component{
/***/
  constructor(props) {
    super(props);

    this.state = {
      wallsJSON: [],
      isLoading: true
    };
  }
/***/
...
}

Next, we will define a fetchWallsJSON method, which, well, does what it says. Leave a couple of lines below the constructor’s closing brace and add the following lines of code:

fetchWallsJSON() {
	console.log(‘Wallpapers will be fetched’);
}

We would like this function to fire once our component has been successfully mounted. Add the componentDidMount method. Most of the described methods go inside the SplashWalls class – I’ll not forget to mention when they don’t.

componentDidMount is a lifecycle method which is fired immediately after the first rendering occurs.

Initial render LifeCycle method call sequence.35

Initial render lifecycle method call sequence. (Image credit: TutorialHorizon36)

Here’s a good explanation of all the React component’s lifecycle methods37. Just remember that since we’re using the newer class syntax, we can omit the getInitialState method. It is substituted by a this.state variable declaration in the constructor.

It’s a good idea to organize methods inside your class in a clean manner. I like to keep all the custom methods separate from the lifecycle methods. You should too.

Let’s declare componentDidMount:

componentDidMount() {
	this.fetchWallsJSON();
}

Notice that inside the fetchWallsJSON method we have logged a message to the console – but where is the console? Hold tight.

Make sure you have the Simulator window selected and press Cmd + Control + Z. From the menu that pops up, select Debug in Chrome. This opens up a new tab. While in the same tab, head over to Dev Tools (Option + Cmd + J). In the console you will find the message “Wallpapers will be fetched”.

Logged message in the console.38

Logged message in the console.

Keep the debugger open for now. Visit unsplash.it/list39 in a new tab. You should see the whole viewport filled with a JSON array. Each element in the array is a JavaScript object holding data for a single wallpaper. This is the data we will be filtering through and grabbing random wallpapers from.

Let us first make fetchWallsJSON do more than just log a message to the console.

  fetchWallsJSON() {
	/***/
    var url = 'http://unsplash.it/list';
    fetch(url)
      .then( response => response.json() )
      .then( jsonData => {
        console.log(jsonData);
      })
	.catch( error => console.log(‘Fetch error ‘ + error) );
	/***/
  }

Refresh the simulator (Cmd + R) or, better, enable live reload by pressing Cmd + Ctrl + Z and choosing Enable live reload. By enabling live reload you don’t have to refresh the simulator each time you make a change to your code. Just save in the IDE and the simulator will automatically be refreshed. If you’ve ever developed an app in Xcode or Android Studio before, you’ll find this feature particularly amazing as you don’t have to hit the Run button and recompile the app every single time you make a change. These little bits make React Native so much more appealing.

On refresh, after waiting a few seconds, you should see the following output in the console:

Retrieved data logged in the console.40

Retrieved data logged in the console.

Good, now we’re able to fetch wallpapers’ JSON data from the API. As you might have noticed there is a little delay before the data is logged to the console. This is because in the background the data is being downloaded from the servers, which takes time.

This looks like a perfect time to add a loading screen.

3. Adding A Loading Screen Link

By the end of this section we will have a loading screen show up while the JSON data is being downloaded.

First, get rid of everything from inside SplashWall class’s render method and add these lines of code:

  render() {
    var {isLoading} = this.state;
    if(isLoading)
      return this.renderLoadingMessage();
    else
      return this.renderResults();
  }

We have two new methods. Let’s declare them too, while we’re at it

  renderLoadingMessage() {
    return (
      
  . <View style={styles.loadingContainer}>
        <ActivityIndicatorIOS
          animating={true}
          color={'#fff'}
          size={'small'} 
          style={{margin: 15}} />
          <Text style={{color: '#fff'}}>Contacting Unsplash</Text>
       
   .</View>
    );
  }

  renderResults() {
    return (
      
  . <View>
        <Text>
          Data loaded
        </Text>
       
   .</View>
    );
  }

Depending on what value the isLoading state variable holds, two different View components will be rendered. If isLoading is true we show a loading spinner followed by the text “Contacting Unsplash”; when isLoading is false (implying data has been loaded) we show the results, which as of now is just a Text component that says “Data loaded”.

But we’re missing something here: we’re not changing the value of isLoading once our data has been downloaded. Let us do just that. Head over to the fetchWallsJSON method and below the line that logs jsonData to the console, add one extra line to update isLoading.

  fetchWallsJSON() {
    var url = 'http://unsplash.it/list';
    fetch(url)
      .then( response => response.json() )
      .then( jsonData => {
        console.log(jsonData);
	/***/
        this.setState({isLoading: false}); //update isLoading 
	/***/
      })
	.catch( error => console.log(‘Fetch error ‘ + error) );
  }

setState41 is one of React’s Component API methods.42 It is the primary method used to trigger UI updates.

Notice, in renderLoadingMessage we have a new component: ActivityIndicatorIOS (put simply, the spinner). We need to import this component before we can use it. Remember when we imported Component 43where we saved a couple of keystrokes? We’ll need to do just that.

var {
  AppRegistry,
  StyleSheet,
  Tex .t,
  View,
  Component,
/***/
  ActivityIndicatorIOS // Add new component
/***/
} = React;

We need to do one more thing before we can see the results. Notice the View containing ActivityIndicatorIOS has style set to styles.loadingContainer. We’ll need to define that. Find the line that says var styles = StyleSheet.create({…. Here you will see there are some styles already defined. These styles are responsible for styling the initial “Welcome to React Native” message in the simulator. Get rid of all of the predefined styles and add just one for the loadingContainer as shown.

var styles = StyleSheet.create({
/***/
  loadingContainer: {
	flex: 1,
    flexDirection: 'row’,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#000'
  }
/***/
});

All of the styles you apply on components in React Native are declared in the manner shown above. StyleSheet.create takes in a JavaScript object containing styles as an argument and then the styles can be accessed using the dot[.] operator. Like we applied the style to wrapper View in the following manner.

<View style={styles.loadingContainer}/>

You’re also allowed to declare styles inline:

<View style={{
	flex: 1,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#000'
  }} />

This makes our code a little cluttered, though. When you have a number of styles applied to a component, it’s always a good idea to store them in a variable.

The styles look a lot like CSS, don’t they? You know why? Because they’re supposed to – they’re not any different. This makes React Native even easier for web developers to pick up. When you build an app in a dedicated IDE (Xcode, for example) you’re provided with a StoryBoard to directly drag and position UI elements like buttons and labels on the screen. You can’t do that in React Native, which – believe me – isn’t a bad thing at all.

React Native makes heavy use of flexbox to position elements on the screen. Once you’re comfortable with flexbox, positioning elements around is a breeze. I will on any day prefer flexbox layout over StoryBoard, period. It’s just one of those things you have to try yourself to tell the difference.

Save the changes, head over to the simulator and press Cmd + R. You should see the loading screen.

Loading screen we just finished building.44

Loading screen we just finished building.

After a few seconds you should see the screen that says “Data loaded”.

Data loaded message is visible once data finishes loading.45

The data loaded message is visible once data finishes loading.

4. Filtering And Picking Random Wallpapers Link

In this section we will filter through the wallpaper data and pick specified number of random wallpapers.

This section will focus more on JavaScript than React Native. We will go through creating a new module (file) that will handle random number generation. If modules in JavaScript sound new to you, consider going through the Node.js modules docs46.

Go to the line above the class declaration and declare a new constant that will tell the app the number of random wallpapers to pick; let’s make it five.

const NUM_WALLPAPERS = 5;

Now we’re going to create a module that’ll help us with the generation of random numbers. This module will export two functions. Let’s look a look at each one of them.

  • uniqueRandomNumbers: This function takes in three arguments. First is the number of random numbers that are to be returned. The next two arguments define the range in which the random numbers are to be returned, namely lowerLimit and upperLimit. If you call the function uniqueRandomNumbers(5, 10, 20) you will be returned an array of five unique random numbers between 10 and 20.
  • randomNumberInRange: This function takes in two arguments defining the lower and upper limit respectively between which a single random number is returned. For example, if you call randomNumberInRange(2, 10) a unique random number between 2 and 10 is returned.

We could have merged both of these functions into one, but as I am a preacher of good quality code, I follow the single responsibility principle47. SRP states, more or less, that each function should do one thing well and not do anything else. Following good programming principles saves you from a number of future headaches.

Create a new file in the same directory as index.ios.js. If we wanted to, we can put these functions in index.ios.js, but think about it: for the kind of purpose this new file serves we can simply copy this file and paste in any of our new projects that requires generation of random numbers and use it from there. Also, this keeps the code within index.ios.js that much cleaner.

We’ll call the file RandManager.js. Shown below is its content:

module.exports = {
	uniqueRandomNumbers(numRandomNumbers, lowerLimit, upperLimit) {
		var uniqueNumbers = [];
		while( uniqueNumbers.length != numRandomNumbers ) {
			var currentRandomNumber = this.randomNumberInRange(lowerLimit, upperLimit);
			if( uniqueNumbers.indexOf(currentRandomNumber) === -1 ) 
				uniqueNumbers.push(currentRandomNumber);
		}
		return uniqueNumbers;
	},

	randomNumberInRange(lowerLimit, upperLimit) {
		return Math.floor( Math.random() * (1 + upperLimit - lowerLimit) ) + lowerLimit;
	}

};

Don’t forget to require the RandManager module in index.ios.js. Just add: var RandManager = require(‘./RandManager.js’); below the use strict; statement. Once we have RandManager ready, we’ll make the following changes to our fetchWallsJSON function:

fetchWallsJSON() {
  var url = 'http://unsplash.it/list';
  fetch(url)
    .then( response => response.json() )
    .then( jsonData => {
    /***/
      var randomIds = RandManager.uniqueRandomNumbers(NUM_WALLPAPERS, 0, jsonData.length);
      var walls = [];
      randomIds.forEach(randomId => {
        walls.push(jsonData[randomId]);
      });

      this.setState({
        isLoading: false,
        wallsJSON: [].concat(walls)
      });
    /***/
    })
    .catch( error => console.log('JSON Fetch error : ' + error) );
}

Once we have the jsonData, we retrieve unique random numbers from RandManager and store them in the randomIds array. We then loop through this array, picking up wallpaper data objects present at a particular randomId and storing them in walls array.

Then we update our state variables: isLoading to false as data has been downloaded; and wallsJSON to walls.

To see the results, modify the renderResults function to resemble the following:

renderResults() {
/***/
  var {wallsJSON, isLoading} = this.state;
  if( !isLoading ) {
    return (
      
  . <View>
        {wallsJSON.map((wallpaper, index) => {
          return(
            <Text key={index}>
              {wallpaper.id}
            </Text>
          );
        })}
       
   .</View>
    );
  }
/***/
}

In the very first line inside renderResults we’re using a new ES2015 feature called destructuring48. With destructuring we have managed to substitute:

var wallsJSON = this.state.wallsJSON,
	isLoading = this.state.isLoading;

with:

var {wallsJSON, isLoading} = this.state;

ES2015 is pretty cool, I am telling you.

Then, inside the View we loop through the retrieved wallsJSON data using map49. Whenever you want to loop through a collection in JSX50 you use the map construct.

Also, when looping through an array or collection and rendering a component, React Native requires you to give a key, a unique ID to each of the child components that renders. That is why you see a key property in

<Text key={index}>

Once the simulator refreshes…

Randomly generated Ids are visible once data finishes loading.51

Randomly generated IDs are visible once data finishes loading.

We see five different random wallpaper IDs being displayed. Change {wallpaper.id} to {wallpaper.author} in renderResults and you should see something like the following.

Author names corresponding to random ids.52

Author names corresponding to random IDs.

Great! Now we’re talking. We are now able to fetch and filter the specified number (five, in this case) of random wallpapers from the API. Looks like we’re done for this section. High five!

5. Adding The Swiper Component Link

In this section we will include a Swiper component in our app. This component will allow us to display wallpapers in a swipeable container.

You’ll learn how to include a third-party React Native component in our app. React Native has amazing community support and on GitHub there is a rich collection53 of all kinds of different third-party components.

For our purposes we will use react-native-swiper54.

Head to the project directory in the terminal and run the following command:

npm install react-native-swiper --save

Now require the Swiper component: add var Swiper = require(‘react-native-swiper’); below use strict.

Let’s try out our newly included Swiper component.

Go to the renderResults method and replace View with Swiper. After doing this, your renderResults should look like this:

renderResults() {
  var {wallsJSON, isLoading} = this.state;
  if( !isLoading ) {
    return (
    /***/
      <Swiper>
    /***/
        {wallsJSON.map((wallpaper, index) => {
          return(
            <Text key={index}>
              {wallpaper.author}
            </Text>
          );
        })}
    /***/
      </Swiper>
    /***/
    );
  }
}

Doing so results in the following:

Each author name visible in its very own container.55

Each author name is visible in its very own container.

Instead of showing the names of authors as a list, we have put them in a swiper which gives each wallpaper its very own screen, which we can swipe across. We need to do a couple more things here: add the following attributes to the Swiper component as shown.

<Swiper
/***/
dot.{<View style={{backgroundColor:'rgba(255,255,255,.4)', width: 8, height: 8,borderRadius: 10, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3,}} />}

activeDot.{<View style={{backgroundColor: '#fff', width: 13, height: 13, borderRadius: 7, marginLeft: 7, marginRight: 7}} />}

loop={false}

onMomentumScrollEnd={this.onMomentumScrollEnd}
/***/
>
  {wallsJSON.map((wallpaper, index) => {
    return(
      <Text key={index}>
        {wallpaper.author}
      </Text>
    );
  })}
</Swiper>

Doing this:

  • Styles the pagination dots (makes the blue dots you see at the bottom in the previous image white and bigger).
  • Disables continuous swiping (loop={false}). That is, once you reach the final page and you swipe further you’re not taken back to the first wallpaper.
  • Will fire onMomentumScrollEnd (which we’ll be delving further into in the next part of the tutorial) each time we’re done swiping.

With this, we’ve come to an end of the first part. What a journey!

To Sum Up The React Native Tutorial Link

  • In the first section you learned how to set up a blank React Native project in Xcode.
  • In the second section we talked about ES2015 classes and why you should prefer the newer syntax along with creating state variables and grabbing raw data from the API.
  • In section three we went over dynamically rendering the app based on the value a state variable holds. Also, we did some light flexbox positioning.
  • In the fourth section we created a brand new module to handle random number generation and also went over including it in the main file.
  • In the last section we added the first third-party component to our app, which was a cakewalk, thanks to Node.

Up until now, to be honest, our app doesn’t look very special. I know. In the next part we will add actual images instead of just author names. Not only that, we will be doing some advanced stuff like creating a custom double-tap detector using the PanHandler API. You will learn how to link a library in Xcode and grant your app access to the Camera Roll. We will also create our very own component and a lot more. Sound interesting? See you in the next part.

(da, ml, og, il)

Footnotes Link

  1. 1 http://ionicframework.com/
  2. 2 https://www.smashingmagazine.com/2014/02/four-ways-to-build-a-mobile-app-part3-phonegap/
  3. 3 https://www.smashingmagazine.com/2016/04/how-to-build-your-first-ios-app-with-javascript/
  4. 4 https://www.smashingmagazine.com/2016/04/finally-css-javascript-meet-cssx/
  5. 5 https://medium.com/ios-os-x-development/an-ios-developer-on-react-native-1f24786c29f0#.avhlz9qsr
  6. 6 https://www.smashingmagazine.com/2016/04/consider-react-native-mobile-app/
  7. 7 https://www.smashingmagazine.com/2016/03/server-side-rendering-react-node-express/
  8. 8 https://www.smashingmagazine.com/2016/09/how-to-scale-react-applications/
  9. 9 https://www.smashingmagazine.com/2017/01/internationalizing-react-apps/
  10. 10 http://unsplash.com/
  11. 11 https://babeljs.io/docs/learn-es2015/
  12. 12 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes
  13. 13 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions
  14. 14 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
  15. 15 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/template_strings
  16. 16 https://facebook.github.io/react/
  17. 17 https://facebook.github.io/react-native/docs/linux-windows-support.html
  18. 18 https://github.com/nashvail/SplashWalls
  19. 19 https://developer.apple.com/xcode/
  20. 20 https://nodejs.org/en/
  21. 21 https://docs.npmjs.com/getting-started/what-is-npm
  22. 22 https://docs.npmjs.com/getting-started/installing-node
  23. 23 https://facebook.github.io/react-native/docs/getting-started.html#content
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2016/02/01-react-native-preview-opt.png
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2016/02/02-react-native-preview-opt.png
  26. 26 https://en.wikipedia.org/wiki/Reverse_domain_name_notation
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2016/02/03-react-native-preview-opt.png
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2016/02/04-react-native-preview-opt.png
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2016/02/05-react-native-preview-opt.png
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2016/02/06-react-native-preview-opt.png
  31. 31 https://www.smashingmagazine.com/wp-content/uploads/2016/02/07-react-native-preview-opt.png
  32. 32 http://unsplash.it
  33. 33 https://reactjsnews.com/composing-components
  34. 34 https://facebook.github.io/jsx/
  35. 35 https://www.smashingmagazine.com/wp-content/uploads/2016/02/32-react-native-preview-opt.png
  36. 36 https://twitter.com/tutorialhorizon
  37. 37 https://facebook.github.io/react/docs/component-specs.html
  38. 38 https://www.smashingmagazine.com/wp-content/uploads/2016/02/08-react-native-preview-opt.png
  39. 39 http://unsplash.it/list
  40. 40 https://www.smashingmagazine.com/wp-content/uploads/2016/02/09-react-native-preview-opt.png
  41. 41 https://facebook.github.io/react/docs/component-api.html#setstate
  42. 42 https://facebook.github.io/react/docs/component-api.html
  43. 43 #componentImport
  44. 44 https://www.smashingmagazine.com/wp-content/uploads/2016/02/10-react-native-preview-opt.png
  45. 45 https://www.smashingmagazine.com/wp-content/uploads/2016/02/11-react-native-preview-opt.png
  46. 46 https://nodejs.org/api/modules.html#modules_modules
  47. 47 https://en.wikipedia.org/wiki/Single_responsibility_principle
  48. 48 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
  49. 49 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
  50. 50 https://facebook.github.io/jsx/
  51. 51 https://www.smashingmagazine.com/wp-content/uploads/2016/02/12-react-native-preview-opt.png
  52. 52 https://www.smashingmagazine.com/wp-content/uploads/2016/02/13-react-native-preview-opt.png
  53. 53 https://react.parts/native
  54. 54 https://github.com/leecade/react-native-swiper
  55. 55 https://www.smashingmagazine.com/wp-content/uploads/2016/02/14-react-native-preview-opt.png

↑ Back to top Tweet itShare on Facebook

Nash Vail has a passion for designing building user interfaces. He is currently a Computer Science undergrad and actively looking for internship opportunities. He has his own little blog you should check out, you can find him on Twitter, GitHub, Dribbble or shoot him a mail at hello@nashvail.me.

  1. 1

    This is not easy to follow. Couple of reasons:

    By default port 8081 was already in use on my machine so I had to change it to something else in xcode.
    This might help.

    There was already ES2015 syntax in my index.ios.js file so part of section 2 is obsolete

    Your code in this article has some typos:

    .

    Why the dot?

    dot.{}

    why the dot again? should be
    dot={}
    Fortunately github repo is ok.

    5
    • 2

      sorry for the mess, hard to style the comment without preview option.

      0
      • 3

        Please remove the “.” from your sample code, or let your users know that they must remove it themselves.

        0
    • 4

      there’s no “use strict” either.

      1
      • 5

        Yeah, I noticed that too – what’s up with that Nash?

        1
      • 6

        Michael J Ryan

        April 18, 2016 10:36 pm

        Modules transpiled by Babel, at least with es2015 will “use strict” in the output.

        1
    • 7

      Give the guy a break. I didn’t realise you were paying for this tutorial? It’s not ideal but in my case, these errors made me pay more attention to the code than I would have done otherwise (not saying that tutorials should come with errors) But anyway – I thought this was great. Thank you for your hard work.

      17
  2. 8

    Is there a way to use regular CSS instead of ?

    -3
    • 9

      Whoa, I agree with @apieceofbart, a preview option is needed. Let’s retry:

      Is there a way to use regular CSS instead of <view style="{}">?

      -4
    • 10

      No, You can’t use regular css in react native.

      1
  3. 11

    Thanks Nash, your effort is appreciated.

    2
  4. 12

    Thanks man, amazing article very helpful.

    -4
  5. 13

    Matt McRuzpaynemeier

    April 12, 2016 5:41 pm

    You have to realize this is not how you build native iOS Applications. For the simple purposes of tinkering, or being straight-up silly, I guess this article has some value. Similar to running OS X on a Windows box, there is no real value here. Apple has provided powerful languages, tools and frameworks to take advantage of the true power of the hardware that makes up devices earning an Apple logo on their backs. If anyone has a real interest in learning this skill, I recommend starting here: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/

    Do not put CSS in your iOS apps. Do not use JavaScript to build iOS apps. If you are new to iOS development, block this tutorial’s URL from your life. Change your hosts file to point it to something more valuable, like http://www.sesamestreet.org.

    -43
    • 14

      So, it’s apparent, then, that you’ve never worked on a small team of developers, or needed to support more than one mobile platform?

      There’s definitely value in having one code base for the two major mobile platforms. Need to add features to your mobile app? Simple, edit the one set of code and you’re done.

      3
      • 15

        Your argument suggests the same idea as having your plumber fix your roof just because he’s there. You limit yourself from day one with the “but one code base!” argument. This isn’t the right approach on Droid either. If there was a platform that allowed my swift code to run on Windows XP, I still wouldn’t use it. I’d use the c# that crap was built for. Temporary cheater code methodologies are nothing more than cutting corners and a guaranteed way to ruin your reputation. None of this stuff is sustainable down the road.

        -11
        • 16

          Bernhardt Scherer

          April 13, 2016 9:21 am

          Exactly. Luckily EVERY company, even the smallest startup, has enough money to hire a team for iOS, Android ah and since Devs are so cheap, for Windows Mobile, too.

          11
          • 17

            Michael Dobekidis

            April 19, 2016 2:48 pm

            Devs are cheap, just not in the US, Germany, UK, France, etc… you get my point.
            This article has some value, but if you want to optimize your app, your should hire a developer for each platform or gather enough money to do so… an idea is nothing if there aren’t the means to implement it.

            All in all a good attempt at native with known widespread “languages” like JS. At least better than Phone-huge-gap

            -7
  6. 18

    I’ve been looking around and I cant find out how to use Oauth APIs with react native anywhere. Can you do a tutorial on that? Thanks.

    1
  7. 19

    Wow, great tutorial!! Quick question, why did you set the dots to white in the last step? Surely it’d be best to pick a solid and a opaque color that’s visible over the white background of the element?

    0
  8. 24

    Nice article Nash!

    0
  9. 25

    Best introductory react/react-native tutorial I have read so far. Thanks for making this.

    1
  10. 26

    Good tutorial! Not sure what’s up with all the jerky comments.

    -1
  11. 27

    Note before starting —

    The article assumes that you already have an apple developer id and provisioning information set up. Xcode won’t let you start a project without this, so you’ll need to go through [that process](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingProfiles/MaintainingProfiles.html) and pay the $99 before you can do the tutorial.

    -7
    • 28

      Gary Oakman

      May 2, 2016 12:09 pm

      The $99 fee is required only when you submit your app to the app store. For the purposes of this tutorial there is no need to pay the $99 fee.

      -1
  12. 29

    To all the naysayers : Why would Facebook themselves invest all this time and effort (allocating a dedicated team of 16 developers to the React project) if they did not believe that this is the future of cross-platform development?

    Why would they build their Facebook Ads manager on React Native and not in Swift?

    Why will QQ, with their measly 860 millions users, rely 100% on React Native for their native app?

    Any outspoken criticism against the framework in this thread is either out of a place of ignorance or some form of bitterness against the evolution of programming applications.

    10

↑ Back to top