React Native: Quick Start and Including Images

Origin Story

I asked a question on Stack Overflow about ~7 months back (at time of writing) about requiring and including images in react native. I figured it was a simple misunderstanding on my part about the directory structure(s) used in iOS development, but it turned out to be both 1) something other people were curious about and 2) an area where the react native team was still stabilizing the API. I got some points on Stack Overflow the other day for the same question and after looking at the question thought I'd like to write about react native.

You've probably heard of React by now if you're a front-end developer and haven't been utterly ignoring the JavaScript community for the past year. If you haven't, no worries — you can read about it here.

There was a really exciting development in the react world earlier this year when the Facebook announced that they had created React Native. That's right, it's what you think it is: React......but for native apps.

cookie monster gif

Cookie Monster is excited

The notion of universal (not isomorphic) JavaScript applications isn't new, but the getting the ability to use something like React on native platforms is a pretty novel and cool idea. Just this line from the landing page is enough to get me really excited

"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"1

native benefits + async execution + npm + web-standards compliance?!?

excitement

That's pretty cool. As I'm want to say, not the end-all, silver-bullet that you might think it is, because nothing is. But still really, really cool. Things seem to be going more and more the way of universal javascript, which is a very exciting thing for someone who's really passionate about JavaScript.

To be sure, there are other platforms and ecosystems (the semantics are fuzzy to me as to what to rightly call all of them, really) that have sought to address the problem of developing one app tens times for ten different platforms. Take Meteor or Ionic as the probably most well-known and best-developed examples of this approach.

React is not a holistic platform like meteor or ionic try to be. Those platforms are much more end-to-end or 'full' stack solutions, whereas React doesn't care at all what database or persistence layer you use, what networking stack you go for, and so on. This, in my view, is a huge advantage because you can take advantage of all the benefits of what react native does well without having to buy into some ecosystem (you don't even have to use the npm registry, but you'd be crazy not to).

Quick Start

So, how to get started? Easily enough:
You'll need:

  • ⇒ some version of node.js (get 5.0.0 and enjoy some of The Future™ -> aka ES6/2015)
  • ⇒ some version of npm
  • xcode (6.3 or higher is required); make sure you've installed the developer tools with:
  • ⇒ watchman & flow (flow is optional), which you can install with homebrew
# if you need the dev tools
xcode-select --install  
brew install flow watchman nvm  
nvm install node && nvm alias default node # installs latest stable node  

Great! You've got all you need to get started. So, let's create a repo, install the react-native-cli tool and get started.

> git init
> npm install -g react-native-cli && react-native init myProjectName
> git add . && git commit -m "Initial commit"

This should have created the xcode and build files you'll need to get going. Next, you'll want to open the xcode file in your newly-initiated project:

open myProjectName/ios/myProjectName.xcodeproj  

Once you've done that, xcode will be up and running and you should see xcode looking something like this:

To start the build, hit the button that sort of looks like a play button; you should see the xcode compiler(s) start to bundle, linked, and build everything:

building react native xcode

You're almost there!

You should see a terminal open, run the transformer/bundler actions, and then launch an iPhone simulator and open up your react app!

react native start screen

As the screen says, you can hit command + R to reload or command + D to open the debugging menu. You can find some pretty sweet debugging tools that'll give you insights into your application and components.

Adding Images

Well, we're running a react application on an iPhone. Stop and enjoy that possibility for a second! Now, your app is incredible but pretty much useless, so let's add an image and at least get something interesting in there.

React native is pretty cool, and so are the benefits you get when working with requiring/adding images (from the react native docs2):

  • ⇒ Same system on iOS and Android.
  • ⇒ Images live in the same folder as your JS code. Components are self-contained.
  • ⇒ No global namespace, i.e. you don't have worry about name collisions.
  • ⇒ Only the images that are actually used will be packaged into your app.
  • ⇒ Adding and changing images doesn't require app recompilation, just refresh the simulator as you normally do.
  • ⇒ The packager knows the image dimensions, no need to duplicate it in the code.
  • ⇒ Images can be distributed via npm packages.

Head to index.ios.js in your project folder and open it up with Atom or whatever editor your prefer. You should see something like this:

'use strict';

const React = require('react-native');  
let {  
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Image,
} = React;

const endemic = React.createClass({  
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to My Cool New App!
        </Text>
        <Image source={require('./assets/images/videos-blue.jpg')}/>
        <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>
    );
  }
});

const styles = StyleSheet.create({  
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('endemic', () => endemic);  

As you can see, it's all react in there — you just have a slightly different set of components available to you. Let's add an image and require it. Add whatever picture you want to somewhere in your project tree; I like to add mine to something like /assets and put whatever, you guessed it, assets I'll be using in there3.

Let's find a fun image to use from Unsplash4:
fall

Add it to your assets directory. One more step and we're done!

'use strict';

const React = require('react-native');

// We need to include the Image component type so we can use it
const {  
  AppRegistry,
  StyleSheet,
  Text,
  Image, 
  View,
} = React;

const myProjectName = React.createClass({  
  render: function() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to our cool new app!
        </Text>
        // Add the image!
        <Image source={require('./assets/fall.jpg')}
               style={{width: 200, height: 100}} />
      </View>
    );
  }
});

const styles = StyleSheet.create({  
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('myProjectName', () => myProjectName);

react native image without percent styling

Wait — that doesn't look super great. Why don't we try to get the image to be full-width? We could try setting a percentage width on the image, but using percentages isn't yet supported. So, we can't do the most elegant thing, but we can at least make things a little cleaner:

'use strict';

const React = require('react-native');  
const {  
  AppRegistry,
  StyleSheet,
  Text,
  Image,
  View,
} = React;

const myProjectName = React.createClass({  
  render: function() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Fall has come at last!
        </Text>
        <View style={{flex: 1}}>
          <Image style={styles.image} source={require('./assets/fall.jpg')}/>
        </View>
      </View>
    );
  }
});

const styles = StyleSheet.create({  
  image: {
    width: 400,
    height: 500
  },
  container: {
    flex: 1,
    paddingTop: 20,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});


AppRegistry.registerComponent('myProjectName', () => myProjectName);  

Well, that's a little better, at least.

Fin

Well, we've started to take a brief glimpse into React Native and learned how to require some images. I hope this helps you get started with react native and encourages you to start building for all the platforms!

Questions, thoughts, ideas, concerns? Let me know in the comments below!


  1. https://facebook.github.io/react-native/

  2. https://facebook.github.io/react-native/docs/images.html#content

  3. When I very first tried out react native months ago, they were still stabilizing the API and even doing something like requiring images was a little tough — I couldn't get it to work properly for some reason.

  4. Unsplash is great for finding beautiful images you can use in different projects or just for fun. Incredible resource!