News

Build apps with Facebook’s React Native framework

Create a JavaScript-powered native cataloguing image app with the React library

Reactapp

Create a JavaScript-powered native cataloguing image app with the React library

Reactapp

GET THE TUTORIAL CODE


So, you’ve been writing JavaScript for a little while now, you’d say you’ve gotten quite good at it, you’ve made websites, a couple of small libraries and even a few web apps.

Thing is, no matter how awesome the web is (and it is fully awesome) the call of the native platform still beckons. You decide to give it a crack, but you’ve never written anything with Objective-C before – sure, there’s this new Swift thing that looks familiar, but the process of building an app is still foreign to you. We could try some transpilers, that is, write some apps in JavaScript and then have something like Titanium figure out what your code is trying to do, but that’s a painful process to get right. We could try out PhoneGap – that’s nice and familiar and you can get great results after some tweaking, but JavaScript optimisation is hard – especially when it’s inside a native wrapper.

What are we to do? Wouldn’t it be great if we could write apps in JavaScript with our favourite IDE but have everything in our views be native – wouldn’t that be ideal? Well, that’s React Native – a supercool framework from Facebook that lets you write your app logic in familiar React.js syntax and then renders all of the view using native iOS/Android elements. It’s not transpiling or reinterpreting your JavaScript code, it’s running it separately in the background. In this tutorial, we’re going to be making a catalogue app, that is, an app that shows us cats (see what we did there?), so let’s get to it!

1. Get React installed

React Native is a complicated piece of kit, so there are quite a few dependancies but thanks to homebrew, NPM and Node.js setting up React Native is simple. To install just run these commands in a terminal window:

brew install watchman
npm install -g react-native-cli

2. Create a new project

Now we have the React Native CLI tools installed, CD to a directory that you want to create your React Native project in and run ‘react-native init catalogue’. This will create a bare-bones project with everything we need.

3. Fix Xcode project/iOS simulator

For some, the Xcode project might not work out of the box, Xcode can fix that for us. Open the Cat-alogue.xcodeproj file inside the folder you just created. Xcode will open. Click on the project tab on the left and select 8.0 from the Deployment Target drop-down menu.

4. Select device

Look at the play button in the top left of Xcode, just to the right of it there should be a small icon with iPhone 4s or something similar, click it and select iPhone 5s or iPhone 6 (depending on your version of Xcode) from the dropdown that appears and hit play.

5. Fix errors

If you get errors, the fix is simple. Click on the tabs showing the error and select the first fix that’s suggested. Hit play and the app should run. The iOS simulator might throw an error so select ‘iOS simulator’ in the menubar and click ‘reset content and settings’ and hit play again.

6. Our bare-bones app

In our iOS simulator, our app will now be open. Go back to the catalogue folder we created and open index.ios.js in your favourite IDE. This is the main entry point for React Native to run our app from. We’re using the virtual DOM to create elements, but instead of DOM elements, we’re using equivalent iOS elements.

7. Clear the house

This React Native project has one view, but we need two views for this tutorial: one for listing our categories, and another for viewing the photos in that category. Delete everything in index.ios.js and insert the following in its place to import the required modules for our project.

'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
Image,
ListView,
TouchableHighlight,
NavigatorIOS,
View,
} = React;
var CatViewing = require('./catViewing');
var List = require("./list")

8. Create a starting point

We now have everything we need except for a view. Add the following code to index.ios.js, it uses the NavigatorIOS module to let us create views, this means we get a lot of things like back buttons and animations between views for free. The initialRoute property determines where our app should find the code for our first view.

var catalogue = React.createClass({
render: function() {
return (
<NavigatorIOS
style={styles.container}
initialRoute={{
title: 'Cat-Alogue',
component: List,
}}
/>
);
}
});

9. Stylings

Let’s create a simple stylesheet. React doesn’t use CSS, it uses a JavaScript polyfill to emulate a limited subset CSS with native components, and as such we define styles like so. AppRegistery exposes our React class to our native code, it’s our true entry point to the application.

var styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
// alignItems: 'center',
backgroundColor: 'white',
},
});
AppRegistry.registerComponent('catalogue', () => catalogue);

10. Create list.js

In index.ios.js we defined the List component as our first view. Create the file ‘list.js’ in our project folder and a file called ‘catViewing.js’. Import the following modules:

'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
Image,
ListView,
TouchableHighlight,
View,
} = React;
var cats = require("./cats"),
thumbCats = [];
var CatViewing = require('./catViewing');
just after that, we’re going to create the List class and all of the functions that it will use to build our view:
var list = React.createClass({
getInitialState : function(){
},
renderCatThumb : function(cat){
},
loadCat_egory : function(category){
},
render: function() {
},
});

11. Find the cats module

If we run our code, we get an error, this is because it can’t find the cats module we defined earlier. You can grab cats.js from FileSilo and add it to our project folder, it’s a really simple JavaScript module that contains URLs for the cat images we’ll be using.

12. Set our initial state

We need to help React make sense of our data for iOS so we use a ListView to list categories and a ListView will only accept a DataSource object as an argument. Inside of getInitialState, add the following code to create an object for each of our categories for making a tab:

...
for(var key in cats){
thumbCats.push({
image : cats[key][0],
title : key
});
}

var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
return { dataSource: ds.cloneWithRows(thumbCats),
};
...

13. Render the thumb cats

Now that we have a data source our ListView can use to render items, we’re going to need a function to define what each list item should look and how it works. We can do this in the renderThumbCat function. Here, we’re using React Native’s iOS analogous virtual DOM to express how the list elements should be laid out.

renderCatThumb : function(cat){
return (
<TouchableHighlight onPress={() => {this.loadCat_egory(cat.title)}} underlayColor="rgba(0,0,0,0.1)">

<View style={styles.cell} >
<Image source={{uri : cat.image}} style={styles.thumbnail} />

<View style={styles.rightContainer}>

<Text style={styles.title}>{cat.title} Cats</Text>

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

14. The first render

We’ve not had much to look at so far, but that’s about to change. We now have almost enough code to render our first view. Once every React Module has been loaded, the render function is the last function called and it will render the view. Now change your render function to the following:

render: function() {
return (
<View style={styles.container}>
<ListView dataSource={this.state.dataSource} renderRow={this.renderCatThumb} style={styles.listView} />
</View>
);
},

15. JsCSS stylings

Add some stylings or everything will be clumped together. We can do this with Stylesheet.create(). This is not CSS, but what Facebook calls JsCSS, a subset of CSS expressed as objects. Each object in styles can be thought of as a class name and each property is a styling. A key difference is that we separate stylings with a comma, not a semicolon.

16. Rendering

Head over to the iOS simulator and hit Cmd/Ctr+R on your keyboard to render. We don’t need to recompile the app, because we’re using JavaScript to determine our views, we can rerender on-the-fly. If your keyboard did nothing you need to go to Hardware>Keyboard>Connect Hardware Keyboard in your iOS Simulator Menu bar.

17. Push a view to the stack

Now we have a scrollable list of categories, but when we tap them, they highlight, but nothing happens. If we want to see the images in the category, we need to push a new view to our stack and pass the relevant images to it for loading. Add the following code to loadCat_egory() and then create the file catViewing.js in our project folder:

...
var catsToView = cats[category];
this.props.navigator.push({
title: category + " Cats",
component: CatViewing,
passProps: {catsToView},
});
...

18. catViewing.js

With loadCategory() we’ve passed everything we need to render our images, but where did we pass it to? What about the CatViewing class we’re about to create in catViewing.js? CatViewing works just the same as our list class worked, except instead of being a ListView, we’re using a ScrollView which gives us a little more flexibility when it comes to how we lay content out. Add the following code to catViewing.js to get started:

'use strict';
var React = require('react-native');
var
{
Image,
PixelRatio,
ScrollView,
StyleSheet,
Text,
View,
} = React;
var CatViewing = React.createClass({
render: function() {
},
});
module.exports = CatViewing;

19. Get our list of cats

The first thing we want to do is get a reference for our list of cats that we passed to the view from our List class. Each React class has a props object which we can access by using ‘this’. We don’t need many functions here for our CatViewing class, in fact we only really need one and that is a render(). So ammend render() to look like the following:

render: function() {
var catsToShow = this.props.catsToView;
return (
<ScrollView contentContainerStyle={styles.contentContainer}>
{catsToShow.map(createThumbRow)}
</ScrollView>
);
},

20. Map our cats

In our scrollView, we have mapped catsToShow to createThumbRow, but we haven’t written that yet! So the actual making of the createThumbRow is a very simple process – for each image we pass to it, it will create an instance of the Picture class we’re about to create. Picture is a very simple class, so it’s very similar to CatViewing in that sense, it only has a render function and all it does is take a wrap for an image in a view and then it will grab that image’s source. Just think of it as if you are wrapping an <img> in a <div> and then setting the src attribute over in HTML.

var createThumbRow = (uri, i) => <Picture key={i} uri={uri} />;
var Picture = React.createClass({
render: function() {
return (
<View style={styles.centering}>
<Image style={styles.imageHolder} source={{uri:this.props.uri}} />
</View>
);
}
});

21. Finish up

We’re almost ready to view all of our cats. If you refresh the iOS simulator, we get a nice big error (we might even crash Xcode!) because we haven’t added styles for the Picture or CatViewing classes. But, that’s simple, if we just add the following after our Picture class closes, we’re all done. Now we can take our Cat-alogue, and put it wherever we want it to be.

var styles = StyleSheet.create({
contentContainer: {
padding: 10,
},
centering : {
alignItems : "center"
},
imageHolder : {
width : 280,
height : 280,
marginBottom : 5

}
});
×