Exploring React Native – Part 2

Previously, in “Exploring React Native (Continued Part 1), we continued to work on our simple app. The app initially consisted of an Image component, Text components, state with data, a couple of TouchableOpacity buttons and styling. The app was to keep track of the number of raccoons the user saw but we wanted to add to it. So, we add a new set of components to track the number of pigeons and added the ScrollView component for scrolling. We used the View component to build cards for each animal and learned different ways to pass styling to components.

In this article, we will learn how to create our own components. Components are the building block of React Native. They come built in but they can also be created. As stated on the React Native documentation, “When you’re building a React Native app, you’ll be making new components a lot. Anything you see on the screen is some sort of component. A component can be pretty simple – the only thing that’s required is a render function which returns some JSX to render.”

At the end of the previous article, all our code was in the “App.js” file. Our code was long and we used the same components for the each animal. We will structure our project by creating folders and files, then grouping them by type.

Let’s get started!

Creating Our Components

I will be working on a Mac using Visual Studio Code as my editor, run the app on the iOS simulator and will be working with the “FirstRNProject” project. If you are using Windows or are targeting Android, I will test the app on the Android emulator at the end of the article. This code will also work if you are using Expo and will also be tested later on.

If you are starting with a new React Native or Expo project or didn’t follow the previous article, here is the code:

App.js

import React, { Component } from 'react';
import { Button, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#bff0d4',
paddingTop: 20
},
image: {
height: 200,
width: 200,
alignSelf: 'center'
},
question: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
plusButton: {
backgroundColor: '#9FC4AD',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
minusButton: {
backgroundColor: '#BAAAC4',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
buttonText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},
cardStyle: {
borderColor: '#535B60',
borderWidth: 2,
margin: 20,
borderRadius: 10,
},
buttonRow: {
flexDirection: 'row',
alignSelf: 'center'
}
});
class App extends Component {
state = {
raccoons: 0,
pigeons: 0
};
//Raccoon Functions
addRaccoons = () => {
this.setState({
raccoons: this.state.raccoons + 1
})
}
removeRaccoons = () => {
if(this.state.raccoons !== 0){
this.setState({
raccoons: this.state.raccoons - 1
})
}
}
//Pigeon Functions
addPigeons = () => {
this.setState({
pigeons: this.state.pigeons + 1
})
}
removePigeons = () => {
if(this.state.pigeons !== 0){
this.setState({
pigeons: this.state.pigeons - 1
})
}
}
render() {
return (
<ScrollView style={styles.container}>
{/* Raccoon */}
<View style={styles.cardStyle}>
<Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
<Text style={styles.question} >How many raccoons did you see last night?</Text>
<Text style={styles.number}>{this.state.raccoons}</Text>
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeRaccoons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<Image style={styles.image} resizeMode='contain' source={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Text style={styles.question} >How many pigeons did you see today?</Text>
<Text style={styles.number}>{this.state.pigeons}</Text>
{/* Pigeon Buttons */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addPigeons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removePigeons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
</ScrollView>
)
}
}
export default App;

Our app looked like this:

As you can see the app looks great but the code is long and somewhat complicated. We are going to create our own components for the image, texts and buttons.

First begin by creating a folder inside the project, called “src”. Inside of the “src” folder, create two more folders, one called “components” and one called “screens”. I have seen others name their “src” folder, “app”, and their “screens” folder, “container”. I prefer “src” and “screens” but you can go with “app” and “container” if you would like.

Here is my project:

Now inside of the “components” folder, let’s create a files for the image, question, counter and buttons. We will named them “OurImage.js”, “Question.js”, “Counter.js” and “Button.js”. Then create a file inside of the “screens” folder called “Main.js”. Also take the “img” folder and move inside of the “src” folder.

Let’s start with the “Main.js” file. Copy everything from “App.js” and paste it into “Main.js”. Then go back to “App.js” and delete the imports from React Native, the styles, state, functions for the buttons and everything that is returned in the render function. What you are left with is:

import React, {Component} from 'react';
class App extends Component {
render() {
return (
);
}
}
export default App;

If you try running the app right now, you will get an error because nothing is being returned in the render function. What we will do is, instead of using a built in component, we will return our main screen, “Main.js”. First import the “Main.js” file located inside the “screens” folder like this:

import Main from ‘./src/screens/Main’;

It is similar to importing built in components from React Native. Now inside the render functions add the following tag:

<Main />

Your “App.js” file should look like this:

import React, {Component} from 'react';
import Main from './src/screens/Main'
class App extends Component {
render() {
return (
<Main />
);
}
}
export default App;

Try running the app again and you will notice there is still an error. The problem is that we need to change the class and export names in the “Main.js” file from “App” to “Main”.

import React, { Component } from 'react';
import { Button, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#bff0d4',
paddingTop: 20
},
image: {
height: 200,
width: 200,
alignSelf: 'center'
},
question: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
plusButton: {
backgroundColor: '#9FC4AD',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
minusButton: {
backgroundColor: '#BAAAC4',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
buttonText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},
cardStyle: {
borderColor: '#535B60',
borderWidth: 2,
margin: 20,
borderRadius: 10,
},
buttonRow: {
flexDirection: 'row',
alignSelf: 'center'
}
});
class Main extends Component {
state = {
raccoons: 0,
pigeons: 0
};
//Raccoon Functions
addRaccoons = () => {
this.setState({
raccoons: this.state.raccoons + 1
})
}
removeRaccoons = () => {
if(this.state.raccoons !== 0){
this.setState({
raccoons: this.state.raccoons - 1
})
}
}
//Pigeon Functions
addPigeons = () => {
this.setState({
pigeons: this.state.pigeons + 1
})
}
removePigeons = () => {
if(this.state.pigeons !== 0){
this.setState({
pigeons: this.state.pigeons - 1
})
}
}
render() {
return (
<ScrollView style={styles.container}>
{/* Raccoon */}
<View style={styles.cardStyle}>
<Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
<Text style={styles.question} >How many raccoons did you see last night?</Text>
<Text style={styles.number}>{this.state.raccoons}</Text>
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeRaccoons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<Image style={styles.image} resizeMode='contain' source={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Text style={styles.question} >How many pigeons did you see today?</Text>
<Text style={styles.number}>{this.state.pigeons}</Text>
{/* Pigeon Buttons */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addPigeons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removePigeons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
</ScrollView>
)
}
}
export default Main;

Reload the app and you still get an error. This is because in the “Main.js”, the Image component can not locate the raccoon image. Change the source location to:

<Image style={styles.image} resizeMode='contain' source={require('../img/raccoon.png')} />

The “..” at the beginning means that the file is located outside of the current folder and the rest of the code states that it is located in the “img” folder and is called “raccoon.png”. If the “img” folder is still outside of “src”, the location will be “../../img/raccoon.png”.

I reloaded the app and was still getting an error regarding the image location, so I closed the Metro Bundler and ran the project again. This time it worked and here is the app again:

Ok, cool. Things are working again. Let’s first work on the image component. Open up the “OurImage.js” file inside of “components” and paste this code in it:

import React from 'react';
import { Image, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
})
const OurImage = () => (
);
export default OurImage;

As you can probably tell, this is a bit different. We import Image and StyleSheet from React Native, create the styles variable and export but we do not create a class. The reason for this is because this will be a stateless component. A stateless component is one that will not use lifecycle hooks, which we have not talked about yet, and has no state.

Copy the image styling from “Main.js” and paste it here. Then copy the Image component from “Main.js” and paste it here as well.

import React from 'react';
import { Image, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
image: {
height: 200,
width: 200,
alignSelf: 'center'
}
})
const OurImage = () => (
<Image style={styles.image} resizeMode='contain' source={require('../img/raccoon.png')} />
);
export default OurImage;

Go into “Main.js”, import OurImage component and replace the Image tags with OurImage.

import { Button, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import OurImage from '../components/OurImage';
const styles = StyleSheet.create({
image: {
height: 200,
width: 200,
alignSelf: 'center'
},
});
class Main extends Component {
render() {
return (
<ScrollView style={styles.container}>
{/* Raccoon */}
<View style={styles.cardStyle}>
<OurImage style={styles.image} resizeMode='contain' source={require('../img/raccoon.png')} />
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<OurImage style={styles.image} resizeMode='contain' source={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Text style={styles.question} >How many pigeons did you see today?</Text>

Reload the app and now we have two raccoon images. Before continuing, let’s clean the code in “Main.js” by removing “image” from styles and the Image component import from React Native. Then inside the OurImage tags remove the style and “resizeMode” props. Rename the source prop to “imageSource”.

I realized that we have not discussed what props are. Props are properties that can be passed from a parent to child component. Certain components like View, do not need props but can take them, such as style. Other components like Image, need props or else they will not work. The built in Image component needs at least a source location for its image and possibly dimensions depending on the type of image.

{/* Raccoon */}
<OurImage imageSource={require('../img/raccoon.png')} />
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<OurImage imageSource={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />

In the “OurImage.js” file we will pass “imageSource” to “source”.

const OurImage = ({ imageSource }) => (
<Image style={styles.image} resizeMode='contain' source={imageSource} />
);

Save both files and reload the app. We have the correct images again. Next component we will tackle is the question component. Inside of “Question.js” add the following:

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
question: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Question = ({ question }) => (
<Text style={styles.question}>{question}</Text>
);
export default Question ;

This is similar to the OurImage component. First import the necessary components from React Native. Then I went ahead and copied the styling from “Main.js” file. After that, create the const Question, which will get a “question” prop, and add a Text component with the “question” prop. Going back to “Main.js”, import Question component and replace both question texts with a Question component, passing it a prop, “question”.

Here is “Main.js”:

import Question from '../components/Question';
{/* Raccoon */}
<View style={styles.cardStyle}>
<OurImage imageSource={require('../img/raccoon.png')} />
<Question question='How many raccoons did you see last night?' />
<Text style={styles.number}>{this.state.raccoons}</Text>
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeRaccoons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<OurImage imageSource={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Question question='How many pigeons did you see today?' />

And “Question.js”:

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
question: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Question = ({ question }) => (
<Text style={styles.question}>{question}</Text>
);
export default Question ;

Next component we will work on is the Counter component. Inside of “Counter.js”, copy and paste all the code from “Question.js”. Replace “Question” with “Counter”, remove the styling and props. You should be left with this:

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
})
const Counter = ({ }) => (
<Text ></Text>
);
export default Counter;

This is a pretty good template, so go ahead, copy this and paste it in “Button.js”. We will work on that file next.

Go to “Main.js”, import Counter and replace the Text tags with Counter. Give these Counters a prop called “count” with the corresponding data. Then copy the styling and paste in “Counter.js”.

import Counter from '../components/Counter';
{/* Raccoon */}
<View style={styles.cardStyle}>
<OurImage imageSource={require('../img/raccoon.png')} />
<Question question='How many raccoons did you see last night?' />
<Counter count={this.state.raccoons} />
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeRaccoons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<OurImage imageSource={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Question question='How many pigeons did you see today?' />
<Counter count={this.state.pigeons} />

Our Counter component will look like this:

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Counter = ({ count }) => (
<Text style={styles.number} >{count}</Text>
);
export default Counter;

Things are looking great! Last component we need to work on is the Button component. First import our Button component inside of “Main.js”. Then copy one of the “PLUS” buttons and paste this in “Button.js”. Then import the necessary components from React Native. Make sure you are exporting Button and have create a “const Button”.

import React from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
const styles = StyleSheet.create({
})
const Button = ({ }) => (
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
);
export default Button;

Go back to “Main.js” and replace the raccoons’ buttons with Button tags. To the Button tag pass a prop for button color, “onPress” function and text. Use ‘#9FC4AD’ for the plus button and ‘#BAAAC4’ for the minus button. It will look like this:

{/* Raccoon Button */}
<View style={styles.buttonRow}>
<Button buttonColor=’#9FC4AD’
onPressed={this.addRaccoons}
text='PLUS'
/>
<Button buttonColor=’#BAAAC4’
onPressed={this.removeRaccoons}
text='MINUS'
/>
</View>

After this, go to the Button component, add button styling from “Main.js” and pass the props to the components.

Here is what you will have:

import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
const styles = StyleSheet.create({
plusButton: {
backgroundColor: '#9FC4AD',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
minusButton: {
backgroundColor: '#BAAAC4',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
buttonText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},
})
const Button = ({ buttonColor, onPressed, text }) => (
<TouchableOpacity onPress={onPressed} style={[styles.plusButton, {backgroundColor:buttonColor}]} >
<Text style={styles.buttonText}>{text}</Text>
</TouchableOpacity>
);
export default Button;

To the TouchableOpacity, we will pass it an array of styles. Although the way it is right now will work, because the “backgroundColor” prop in the array is called after “styles.plusButton” and will override the background color inside of “plusButton”, I would like to rename “plusButton” to “buttonStyling”. Then delete “minusButton” from styles and remove “backgroundColor” from “buttonStyling”. Rename the style prop in TouchableOpacity and you have this:

import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
const styles = StyleSheet.create({
buttonStyling: {
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
buttonText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},
})
const Button = ({ buttonColor, onPressed, text }) => (
<TouchableOpacity onPress={onPressed} style={[styles.buttonStyling, {backgroundColor:buttonColor}]} >
<Text style={styles.buttonText}>{text}</Text>
</TouchableOpacity>
);
export default Button;

After saving all the files, I reload the project and got an error. The error was because I had imported Button from React Native in “Main.js” and so it needs to be removed. It may actually be best to rename “Button.js” to “OurButton.js”, this way we can distinguish between our custom button component and the built in one. Don’t forget to change “Button” to “OurButton” in “Main.js” and “OurButton.js”.

Now that the errors have been fixed, here is what I am left with:

As you can see, the buttons for the pigeon section are not correct. This is because we removed all the button’s styling from “Main.js”. Let’s delete these buttons and use our Button component instead. If you want, simply copy the raccoon buttons and pass it the correct “onPress” functions.

<OurButton buttonColor='#9FC4AD'
onPressed={this.addPigeons}
text='PLUS'
/>
<OurButton buttonColor='#BAAAC4'
onPressed={this.removePigeons}
text='MINUS'
/>

Save and reload.

Excellent! Our app is running and working correctly on iOS, let’s open up the Android emulator and make sure it is working there too.

Looking good on Android. Now, let’s test it on Expo.

Expo looking great too. At this point, I suggest going to the “Main.js” and removing components and styles that are no longer used.

Main.js

import React, { Component } from 'react';
import { ScrollView, StyleSheet, View } from 'react-native';
import OurImage from '../components/OurImage';
import Question from '../components/Question';
import Counter from '../components/Counter';
import OurButton from '../components/OurButton';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#bff0d4',
paddingTop: 20
},
cardStyle: {
borderColor: '#535B60',
borderWidth: 2,
margin: 20,
borderRadius: 10,
},
buttonRow: {
flexDirection: 'row',
alignSelf: 'center'
}
});
class Main extends Component {
state = {
raccoons: 0,
pigeons: 0
};
//Raccoon Functions
addRaccoons = () => {
this.setState({
raccoons: this.state.raccoons + 1
})
}
removeRaccoons = () => {
if(this.state.raccoons !== 0){
this.setState({
raccoons: this.state.raccoons - 1
})
}
}
//Pigeon Functions
addPigeons = () => {
this.setState({
pigeons: this.state.pigeons + 1
})
}
removePigeons = () => {
if(this.state.pigeons !== 0){
this.setState({
pigeons: this.state.pigeons - 1
})
}
}
render() {
return (
<ScrollView style={styles.container}>
{/* Raccoon */}
<View style={styles.cardStyle}>
<OurImage imageSource={require('../img/raccoon.png')} />
<Question question='How many raccoons did you see last night?' />
<Counter count={this.state.raccoons} />
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<OurButton buttonColor='#9FC4AD'
onPressed={this.addRaccoons}
text='PLUS'
/>
<OurButton buttonColor='#BAAAC4'
onPressed={this.removeRaccoons}
text='MINUS'
/>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<OurImage imageSource={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Question question='How many pigeons did you see today?' />
<Counter count={this.state.pigeons} />
{/* Pigeon Buttons */}
<View style={styles.buttonRow}>
<OurButton buttonColor='#9FC4AD'
onPressed={this.addPigeons}
text='PLUS'
/>
<OurButton buttonColor='#BAAAC4'
onPressed={this.removePigeons}
text='MINUS'
/>
</View>
</View>
</ScrollView>
)
}
}
export default Main;

OurImage.js

import React from 'react';
import { Image, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
image: {
height: 200,
width: 200,
alignSelf: 'center'
}
})
const OurImage = ({ imageSource }) => (
<Image style={styles.image} resizeMode='contain' source={imageSource} />
);
export default OurImage ;

Question.js

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
question: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Question = ({ question }) => (
<Text style={styles.question}>{question}</Text>
);
export default Question;

Counter.js

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Counter = ({ count }) => (
<Text style={styles.number} >{count}</Text>
);
export default Counter;

OurButton.js

import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
const styles = StyleSheet.create({
buttonStyling: {
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
buttonText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},
})
const OurButton = ({ buttonColor, onPressed, text }) => (
<TouchableOpacity onPress={onPressed} style={[styles.buttonStyling, {backgroundColor:buttonColor}]} >
<Text style={styles.buttonText}>{text}</Text>
</TouchableOpacity>
);
export default OurButton;

Great job! We took each element of the animal card and created a reusable component. We have a component for the image, question, counter and buttons.

In the next article, we will use these custom components to add a third animal. The question will have a text input and instead of using a photo we find online, we will allow users to take a picture or use an image from the photos. Till then, make changes to this code and try to create a card component with our custom components.

Exploring React Native – Part 1.1

In the last article, titled “Exploring React Native”, we used a few components to create a simple app. The app consisted of an Image component, a couple Text components, data that changed with user interaction, and a couple of buttons created with the Button component and TouchableOpacity component.  We styled each component and at the end, had a counter app.

But there are a lot of components we did not cover and the ones we did cover, can be used in other ways. So, in this article, we will continue to use the project from the previous article to learn more about React Native’s components. The components we will be focusing on in this article are the ScrollView and View components. The ScrollView component is similar to View but allows for scrolling. The View component is one that we used in the previously but in this article, we will be using it to create sections in the app. As well, we will be passing a network image to the Image component and will learn a bit more about styling.

Let’s get started!

More Built In Components

I will be working on a Mac using Visual Studio Code as my editor, run the app on the iOS simulator and will be working with the “FirstRNProject” project. If you are using Windows or are targeting Android, I will test the app on the Android emulator at the end of the article. This code will also work if you are using Expo and will also be tested later on.

Open the App.js file and this is what we have from last time:

import React, { Component } from 'react';
import { Button, Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#bff0d4',
alignItems: 'center',
},
image: {
height: 200,
width: 200,
marginTop: 100,
marginBottom: 20
},
question: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 20
},
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 20
},
plusButton: {
backgroundColor: '#9FC4AD',
width: 200,
borderRadius: 10,
margin: 10
},
minusButton: {
backgroundColor: '#BAAAC4',
width: 200,
borderRadius: 10,
margin: 10
},
buttonText: {
fontSize: 40,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
}
});
class App extends Component {
state = {
raccoons: 0
};
addMore = () => {
this.setState({
raccoons: this.state.raccoons + 1
})
}
removeOne = () => {
if(this.state.raccoons !== 0){
this.setState({
raccoons: this.state.raccoons - 1
})
}
}
render() {
return (
<View style={styles.container}>
<Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
<Text style={styles.question} >How many raccoons did you see last night?</Text>
<Text style={styles.number}>{this.state.raccoons}</Text>
<TouchableOpacity onPress={this.addMore} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeOne} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
)
}
}
export default App;

First a quick recap of the code above.

We first imported the components we were going to use from React Native. These components were the Button, Image, StyleSheet, Text, TouchableOpacity and View components. Then we created a styles variables that contained all the styling objects we used to style the components. After that, we created a state for the counter which would change with the pressing of either “PLUS” or “MINUS” buttons. Then inside the render function we had a View component that wrapped the Image, Text and TouchableOpacity components and each was styled accordingly.

Open the Terminal or Command Prompt to run the project. If you are using Visual Studio Code, there is an “integrated terminal, initially starting at the root of your workspace.” Using this terminal, you can run the React Native iOS/Android start commands, or if using Expo, the Expo start command from the editor. You can learn more about Visual Studio Code’s terminal here, https://code.visualstudio.com/docs/editor/integrated-terminal. What you will have is the following:

The app looks great but what if we wanted to create a list of animals, each with its own image, text, counter and buttons? Well, let’s copy the components between the View tags and paste them right after the “MINUS” button but before the closing View tag. Your code will look like this:

<View style={styles.container}>
{/* Raccoon One */}
<Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
<Text style={styles.question} >How many raccoons did you see last night?</Text>
<Text style={styles.number}>{this.state.raccoons}</Text>
<TouchableOpacity onPress={this.addMore} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeOne} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
{/* Raccoon Two */}
<Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
<Text style={styles.question} >How many raccoons did you see last night?</Text>
<Text style={styles.number}>{this.state.raccoons}</Text>
<TouchableOpacity onPress={this.addMore} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeOne} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>

When you save the file and reload the app, you will see this:

That doesn’t look right. We can barely see that there is another image of a raccoon at the bottom of the screen and we can’t scroll down to view the rest of the app. In order for the app to scroll we will use the ScrollView component. According to the React Native documentation, “The ScrollView is a generic scrolling container that can host multiple components and views.” There is another option we could use, called FlatList. The difference between the two, is that, ScrollView renders all of its children components, or the components between its tags, at once. While FlatList renders its items when they appear on the screen and removes them once off the screen. Therefore, if you have a large list, using ScrollView will slow down rendering and increase memory usage. For this app, our list will be short and ScrollView will be used but in later articles we will be using the FlatList component.

Let’s first import the ScrollView component and replace the View tags with ScrollView, save the file and reload. This is what will happen:

This error occurs because of the layout prop “alignItems: ‘center’” that is passed to the styling of the ScrollView components. To fix it remove “alignItems: ‘center’” from “container” in styles. Save the file, reload and now the app will look like this:

It’s not perfect but we can now scroll to through the app and see the second image, along with the text and buttons. To fix the styling of the images and buttons simply add “alignSelf: ‘center’” to the “image”, “plusButton” and “minusButton” styles.

image: {
height: 200,
width: 200,
marginTop: 100,
marginBottom: 20,
alignSelf: 'center'
},
plusButton: {
backgroundColor: '#9FC4AD',
width: 200,
borderRadius: 10,
margin: 10,
alignSelf: 'center'
},
minusButton: {
backgroundColor: '#BAAAC4',
width: 200,
borderRadius: 10,
margin: 10,
alignSelf: 'center'
},

Great! Everything is now centered and we can scroll.

It doesn’t make sense to keep track of the number of raccoons twice, so let’s find an image of another animal online.

If you recall, in the previous article we saved the image of the raccoon in our project under the ‘img’ folder, then passed it to the Image component. By doing so we were using a static image. The Image component can display various types of images and what I want to do now is use a network image. I went online and found an image of a pigeon and got the URL to the image.

Now if you replace the location of the second raccoon image with an URL, like this:

<Image style={styles.image} resizeMode='contain' source={require('https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png')} />

Then you will get an error like this:

That’s because, passing a network image is a little different than passing a static image. Inside of “source={}”, replace it with “{uri: ‘URL_OF_THE_IMAGE’}”. It will look like this:

<Image style={styles.image} resizeMode='contain' source={{ uri: ‘URL_OF_THE_IMAGE’ }} />

So if we replace ‘URL_OF_THE_IMAGE’ with the actual URL, we will have this:

<Image style={styles.image} resizeMode='contain' source={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />

Another key difference between static and network images is that, network images require that the dimensions of the image be specified. Our ‘image’ style object has specified width and height dimension, so our image will appear. Had those dimension not been there, the image would not be displayed.

Save the file and reload the app to get this:

Now I know not everyone likes this bird but I liked how it looked and it a bird, I would say, most people see on a regular basis. You can choose another bird or another animal entirely, it’s totally up to you. There’s just a couple more things that need changing, such as the text, adding the new counter data to the state and creating new functions for the new pigeon buttons.

Changing the text is simple, go to the Text component that corresponds to the second animal, in my case the pigeon, and change it to something like, “How many pigeons did you see today?”. Then add “pigeons: 0” to the state and replace “{this.state.raccoons}” with “{this.state.pigeons}” in the following Text component. Next we can rename the existing functions for the buttons to “addRaccoons” and “removeRaccoons” then copy and paste them right below. For the second set of functions, replace “raccoons” with “pigeons”. Remember to keep the camel case coding style and capitalize the “P” in pigeon. Also don’t forget to go to the TouchableOpacity components and rename the functions accordingly. If you are having any issues, here is the code:

class App extends Component {
state = {
raccoons: 0,
pigeons: 0
};
//Raccoon Functions
addRaccoons = () => {
this.setState({
raccoons: this.state.raccoons + 1
})
}
removeRaccoons = () => {
if(this.state.raccoons !== 0){
this.setState({
raccoons: this.state.raccoons - 1
})
}
}
//Pigeon Functions
addPigeons = () => {
this.setState({
pigeons: this.state.pigeons + 1
})
}
removePigeons = () => {
if(this.state.pigeons !== 0){
this.setState({
pigeons: this.state.pigeons - 1
})
}
}
render() {
return (
<ScrollView style={styles.container}>
{/* Raccoon */}
<Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
<Text style={styles.question} >How many raccoons did you see last night?</Text>
<Text style={styles.number}>{this.state.raccoons}</Text>
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeRaccoons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
{/* Pigeon */}
<Image style={styles.image} resizeMode='contain' source={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Text style={styles.question} >How many pigeons did you see today?</Text>
<Text style={styles.number}>{this.state.pigeons}</Text>
<TouchableOpacity onPress={this.addPigeons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removePigeons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</ScrollView>
)
}
}

I’ve added comments, “{/* Raccoon */}” and “{/* Pigeon */}”, to help indicate that the following set of code corresponds to a particular animal. Writing comments can help you identify sections of code, especially once the code starts to get long and complicated. One thing to note is that when commenting inside JSX, where tags are used like in the above, you need to wrap the comment inside of “{/* YOUR_COMMENT */}”. Outside of JSX, you can use “// YOUR_COMMENT” for a single line comment or “/* YOUR_COMMENT */” for a multi-line comment.

Once saved and reloaded, you will be able to scroll through the app and press the buttons to increase or decrease the counters. Here is how it will look:

Great! Let’s now work on styling the app a bit more by using React Native’s View component.

Right now the app is one continuous page with images, text and buttons. To help separate each section and make the app more user friendly, we will create a border around the raccoon and pigeon set of components. It’s like creating a card for each animal and the card contains all the content for that one subject. This can simply be done by wrapping each set of components in a View and passing it a set of styles.

First, import the View component if you deleted it and create two set of opening and closing View tags. Then copy the set of raccoon components and paste them inside the first View. Repeat for the pigeon components but paste those in the second View. This is what you should have:

<ScrollView style={styles.container}>
{/* Raccoon */}
{/* First View */}
<View>
<Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
<Text style={styles.question} >How many raccoons did you see last night?</Text>
<Text style={styles.number}>{this.state.raccoons}</Text>
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeRaccoons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
{/* Pigeon */}
{/* Second View */}
<View>
<Image style={styles.image} resizeMode='contain' source={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Text style={styles.question} >How many pigeons did you see today?</Text>
<Text style={styles.number}>{this.state.pigeons}</Text>
<TouchableOpacity onPress={this.addPigeons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removePigeons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</ScrollView>

We will now create a new set of styles called “cardStyle” and pass it to both View components. To “cardStyle”, we will add a border color and width. This will create the border around each set of components.

cardStyle: {
borderColor: '#535B60',
borderWidth: 2
}

Save the file and reload the app. Wait a minute, this doesn’t look right.

I can see that there is a line separating the raccoon and pigeon cards but that’s about it. We will need to style this some more.

First add “margin: 20” to “cardStyle”, this will create space between the outside of the border and the edge of the screen. We can then go into the “image” style and remove both margins.

Looking better but I don’t like the border, it’s too boxy. This is a quick fix, add “borderRadius: 10” to “cardStyle”. Also notice that the top border of the raccoon card is being cut off by the iPhone X notch. Let’s add “paddingTop: 20” to the “container” style.

Looking awesome! Our styling is as follows:

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#bff0d4',
paddingTop: 20
},
image: {
height: 200,
width: 200,
alignSelf: 'center'
},
question: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 20
},
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 20
},
plusButton: {
backgroundColor: '#9FC4AD',
width: 200,
borderRadius: 10,
margin: 10,
alignSelf: 'center'
},
minusButton: {
backgroundColor: '#BAAAC4',
width: 200,
borderRadius: 10,
margin: 10,
alignSelf: 'center'
},
buttonText: {
fontSize: 40,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},
cardStyle: {
borderColor: '#535B60',
borderWidth: 2,
margin: 20,
borderRadius: 10,
}
});

Before continuing with styling, I would like to over the different ways you can style a component.

Although not mentioned before, you can simply pass styles to a component using inline styling. Here is an example:

<View style={{ flex: 1, borderColor: ‘red’, borderWidth: 2 }} >

Or, as we have been doing, we can put all the styling in one location and reference it when needed like this:

const styles = StyleSheet.create({
container: {
flex: 1,
borderColor: ‘red’,
borderWidth: 2
}
});
<View style={styles.cardStyle}>

Both styling methods will style the component the same, but by having the styling outside of the render function, we are making the code cleaner and easier to read.

We can also mix and use both by passing style an array, which can help has pass specific styling to only one particular component, while also passing a set of styles other components use. Here is an example:

<View style={[ styles.container, { margin: 20 } ]} >

The styling is almost perfect but I want to add a bottom margin to the pigeon’s View component because I want some spacing between the bottom of the screen and the bottom of the pigeon card. We will pass “cardStyle” and “marginBottom: 60” to only the second View component. Here is how it is done:

{/* Pigeon */}
{/* Second View */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<Image style={styles.image} resizeMode='contain' source={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Text style={styles.question} >How many pigeons did you see today?</Text>
<Text style={styles.number}>{this.state.pigeons}</Text>
<TouchableOpacity onPress={this.addPigeons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removePigeons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>

The bottom of the pigeon card is visible. This is looking great!

Continuing to focus on styling, let’s have the two buttons placed next to each other. Here we will be using the View component again. First inside the raccoon’s View component create a View right after the counter text. Then copy and paste both TouchableOpacity components inside of the View tags. Then inside the pigeon’s View component, do the same for those buttons.

<ScrollView style={styles.container}>
{/* Raccoon */}
<View style={styles.cardStyle}>
<Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
<Text style={styles.question} >How many raccoons did you see last night?</Text>
<Text style={styles.number}>{this.state.raccoons}</Text>
{/* Raccoon Buttons */}
<View>
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeRaccoons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<Image style={styles.image} resizeMode='contain' source={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Text style={styles.question} >How many pigeons did you see today?</Text>
<Text style={styles.number}>{this.state.pigeons}</Text>
{/* Pigeon Buttons */}
<View>
<TouchableOpacity onPress={this.addPigeons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removePigeons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
</View>
</ScrollView>

If you save the file and reload the app, you will notice that nothing happens. We will need to create a new style called “buttonRow”, pass it “flexDirection: ‘row’”, then pass this style to the buttons’ View components. By default “flexDirection” is set to column, because of this, components are stacked on top of each other. But by setting “flexDirection” to row, the components in that View will be stacked side by side.

buttonRow: {
flexDirection: 'row'
}
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addRaccoons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removeRaccoons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>
{/* Pigeon Buttons */}
<View style={styles.buttonRow}>
<TouchableOpacity onPress={this.addPigeons} style={styles.plusButton} >
<Text style={styles.buttonText}>PLUS</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.removePigeons} style={styles.minusButton}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>
</View>

Now the app looks like this:

Oh no! The buttons don’t fit properly. Let’s make the buttons smaller by changing the text’s size and decreasing its width.

plusButton: {
backgroundColor: '#9FC4AD',
width: 150,
borderRadius: 10,
margin: 10,
alignSelf: 'center'
},
minusButton: {
backgroundColor: '#BAAAC4',
width: 150,
borderRadius: 10,
margin: 10,
alignSelf: 'center'
},
buttonText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},

Better but still needs work. We can decrease the button’s margins and center the button’s View component.

plusButton: {
backgroundColor: '#9FC4AD',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
minusButton: {
backgroundColor: '#BAAAC4',
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
buttonText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},
buttonRow: {
flexDirection: 'row',
alignSelf: 'center'
}

At this point, the app looks wonderful but I have tested our code only on the iOS simulator. I want to make sure for those using Windows or targeting Android, that we have the same results. After opening the Android emulator and running the project, I have this:

The app works! I knew it would but there are times that certain components appear differently on iOS than they do on Android. We saw these differences when working with React Native’s Button component. But in this case, the app looks and works the same on both Android and iOS.

Now for those using Expo, I mentioned at the beginning that the code used in this project would also work for you guys. To ensure this is true, I am going to copy the code and paste it in an Expo project we created a while back called, “FirstExpoProject”. Here is the app on a real iPhone X Max:

Yes, app works and looks great! It could probably use more padding at the top and bottom of the screen. Unfortunately, I do not own an Android device but since the app worked on the Android emulator, I am certain it will work on an Android device.

This is where we will leave off for this article. We added ScrollView to our app, allowing us to the ability to scroll and add more content. Then we added a new animal and passed a network image to the Image component. Lastly, using View and some new styling skills we created cards to contain each subject. I suggest you play around with the code because following steps is one thing but when you try it on your own, that’s when you really learn.

In the next article, we will continue to expand our React Native skills using this project. The code in this project was getting long and could be cleaned up. For one, we will learn about creating components and a few more things. See you in the next article.

Exploring React Native

In the previous article, titled “Getting Started with React Native”, we briefly went over what React Native is. We went through the installation process for the Expo CLI and the React Native CLI. The last thing we did was create an Expo and React Native project and made changes to the code, then run the projects.

But at the end of the article you may have wondered, “Now what?”. In this article I will show you some of the built in components that come with React Native. We will use these components to create a fairly simply one screen app that will keep track of a number that can be increased and decreased by a button. The app will teach you how to add an image, text, buttons, keep track of data and style all these components.

Let’s begin!

Built In Components

Begin by opening your project in the code editor of your choice, remember I use Visual Studio Code. If you recall, in the last article there were two ways to create a project. We created an Expo project, called “FirstExpoProject,” and a React Native project, called “FirstRNProject”. I will be using the “FirstRNProject” project but the code in this article will work for both.

In the Explorer, select App.js, open it and delete all the code inside of the file. Throughout this article I will be showing you the code I write, some times it will only be a snippet of the file and I will use “…” to indicate there is more code above and/or below that snippet. At the end of the article I will post the entire code for the App.js file.

The first two line of code will be the following:

import React, { Component } from ‘react’;
import { StyleSheet, Text, View } from ‘react-native’;

The second line is important to us because this is where we will be importing all of the built in components. The StyleSheet allows us to create a specific set of styles for our components, Text component allows us to create text and the View component is one of the fundamental components for the user interface. To learn more about this components and the others provided by React Native check out this link, https://facebook.github.io/react-native/docs/components-and-apis.

Next, create a variable named styles. This is where we will create a StyleSheet and style our components.

const styles = StyleSheet.create({

)};

Time to create the class and export it. Here is how the code will look:

class App extends Component {

}
export default App;

Inside the class, we need to add the render function and return our View component. Save the file.

class App extends Component {
   render() {
     return (
     <View />
     )
   }
}

At this point we can run the app. As I mentioned before I am using the project we created with the React Native CLI, therefore I will open a Terminal on my Mac and head to the directory where the project is located and enter the following command:

react-native run-ios

If you are using Windows or simply want to test on Android, type the following into the Terminal or Command Prompt:

react-native run-android

If you decided to work with the Expo project, type the following into the Terminal or Command Prompt and use one of the methods from the previous article to run the app on your phone or simulator/emulator:

expo start

Again, I am using a Mac and for the time being will be using the iOS simulator. Later on I will use the Android emulator to point out some styling differences.

What you will see when the app is up and running is a white, blank screen. Here is the app running on the iOS simulator:

A blank, white screen looks dull, let’s change that by adding some color to the background:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#bff0d4'
  }
});

class App extends Component {
   render() {
     return (
     <View style={styles.container} />
   )
   }
}

First we add a style prop to the View component. In styles we create a style “container” and gave it a flex of 1 and a background color. “flex: 1”, simply tells the View component to take up all the space available. To learn more about flex, go here https://facebook.github.io/react-native/docs/height-and-width. The color give to the “backgroundColor” can be written in a few ways for React Native, here is a link to learn more, https://facebook.github.io/react-native/docs/colors. If you’ve ever done web development and used CSS, the way to style these components will look familiar. Save the file and if you don’t see the change, reload the simulator/emulator. You can reload by pressing the “Command” and “R” keys for the iOS simulator. For Android emulator, tap “R” twice.

Ok now that we have some color, why not add an image to our app. First thing you need is an image. I found one online of a raccoon, download it and put in a new folder I created inside the project called “img”. But you can also use different type of images, such as using an URL for an image found online. Some of types of images need to have a specific height and width passed to it. Learn more here, https://facebook.github.io/react-native/docs/image. Let’s import the Image component.

import { Image, StyleSheet, Text, View } from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#bff0d4',
    alignItems: 'center',
  }
});

class App extends Component {
  render() {
    return (
    <View style={styles.container}>
    <Image resizeMode='center' source={require('./img/raccoon.png')} />
    </View>
    )
  }
}

Inside the “container” style, I added “alignItems: ‘center’” which centers all the components inside of View horizontally. Next, inside the View component I added the Image component and gave the source the location to the image of the raccoon I am using. I also added “resizeMode=’center’” because the image was large and not displaying properly, this will center the image in the view. Here is what I end up with:

You see that the image is still too large, so we are going to change that.

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#bff0d4',
    alignItems: 'center',
  },
  image: {
    height: 200,
    width: 200
  }
});

class App extends Component {
  render() {
    return (
      <View style={styles.container}>
      <Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
      </View>
    )
  }
}

Create a new style named “image” and give it a height and width. Pass the style to the Image component and change the “resizeMode” to “contain”. This will ensure the image is resized properly to fit the height and width given.

You will notice the image is too close to the top of the screen and a piece of the ears are cut off. To fix this, add “marginTop” and give it a value of 100. You can play around with the number to get the desired spacing between the top of the screen and the image.

image: {
  height: 200,
  width: 200,
  marginTop: 100
}

Here is what we have:

Inside the View component and right below the Image component, lets add a Text component with the following text, “How many raccoons did you see last night?”.

return (
  <View style={styles.container}>
  <Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
  <Text>How many raccoons did you see last night?</Text>
  </View>
)

The text will appear right below the image but it needs some styling. Create a new style named “question” and give it a font size of 20, make it bold, center and change the color. Don’t forget to pass the prop in the Text component.

<Text style={styles.question}>How many raccoons did you see last night?</Text>
question: {
   fontSize: 20,
   fontWeight: 'bold',
   textAlign: 'center',
   color: '#535B60'
}

Looking much better. Next add a new Text component underneath the question which will track the number of raccoons you see. The styling will be similar to that of the question but the font size will be much bigger.

<Text style={styles.number} >0</Text>
number: {
   fontSize: 60,
   fontWeight: 'bold',
   textAlign: 'center',
   color: '#535B60'
}

Here is what we now have:

When we see a raccoon, we will need to be able to press a button which will increase the number or decrease the number. React Native comes with a built in component called Button and we will use it to create a button for increasing the value. Later on, we will use another component that allows for more customization.

import { Button, Image, StyleSheet, Text, View } from 'react-native';
<View style={styles.container}>
  <Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
  <Text style={styles.question} >How many raccoons did you see last night?</Text>
  <Text style={styles.number}>0</Text>
  <Button title='PLUS' color='#535B60' />
</View>

Let’s add the Button component right after the Text component display the number. We pass it a title, “PLUS”, and a color. At the moment our button does not do anything. One thing about the Button component is that they look different on iOS than they do on Android. I am going to run the Android emulator and show you the difference.

Here is the button on Android:

And here is the button on iOS:

Notice how on Android the button has “PLUS” in a white font and is surrounded by the color we provided. But on iOS only the text “PLUS” appears and it is in the color we provided. This is something you will notice when working with React Native and you will need to style your components accordingly.

Before telling the button what to do every time it is pressed, lets create a state that will store our number data. Currently, the number of raccoons seen is set to zero but we want it to change with the pressing of the button.

Create a state with “raccoons” set to zero inside of the class App and before the render function. Then use the data to replace the hard coded zero in the Text component.

class App extends Component {
  state = {
    raccoons: 0
  };

render() {
  return (
    <View style={styles.container}>
    <Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
    <Text style={styles.question} >How many raccoons did you see last night?</Text>
    <Text style={styles.number}>{this.state.raccoons}</Text>

Notice how I replaced the “0” in the second Text component with “{this.state.raccoons}”, this calls “raccoons” in the state. Change the “0” in the state to another number, save, and see that it changes.

We’re now ready to make our button do something. Create a function called “addMore” and set “raccoons” to increase by 1. Then in the Button component, add the prop “onPress” and pass it the “addMore” function.

addMore = () => {
  this.setState({
    raccoons: this.state.raccoons + 1
  })
}
<Button onPress={this.addMore} title='PLUS' color='#535B60' />

Save the file and see that when you press the button, the counter will increase by one. Here is how it will look:

We can increase the counter but what if we made a mistake and want to decrease the counter? Well, we can create another button that will do just that. This time we will use TouchableOpacity component to create a custom button. Begin by importing TouchableOpacity and adding the component right after the Button component we have in the class. We will wrap the TouchableOpacity around a Text component.

import { Button, Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
<Button onPress={this.addMore} title='PLUS' color='#535B60' />

<TouchableOpacity>
<Text>MINUS</Text>
</TouchableOpacity>

Save the file and see that the button needs some styling. We will add styling to the text to change the font size but also to the TouchableOpacity component to make it stand out.

button: {
  backgroundColor: '#BAAAC4',
  width: 200,
  borderRadius: 10
},
buttonText: {
  fontSize: 40,
  fontWeight: 'bold',
  textAlign: 'center',
  color: '#535B60'
}
<TouchableOpacity style={styles.button}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>

We will give the TouchableOpacity component a background color, width of 200 and border radius of 10 to round the corners. To the Text, same as before, font size of 40, bold, align it to the center and give a color. Here is how it will look:

The “Minus” button currently does nothing. We will create a function and pass it to the TouchableOpacity component, just like we did to the Button component.

removeOne = () => {
  this.setState({
    raccoons: this.state.raccoons - 1
  })
}
<TouchableOpacity onPress={this.removeOne} style={styles.button}>
<Text style={styles.buttonText}>MINUS</Text>
</TouchableOpacity>

Test the app! You can add to the counter and remove from it as well. The “MINUS” button is working but it should stop when it reaches zero, we can’t see a negative number of raccoons. This can be easily fixed by adding an if statement to check the current value of “raccoons”.

removeOne = () => {
  if(this.state.raccoons !== 0){
    this.setState({
      raccoons: this.state.raccoons - 1
    })
  }
}

Before calling this app complete, let’s make the “PLUS” button look like the “MINUS” button and do some other styling changes.

import React, { Component } from 'react';
import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#bff0d4',
    alignItems: 'center',
  },
  image: {
    height: 200,
    width: 200,
    marginTop: 100,
    marginBottom: 20
  },
  question: {
    fontSize: 30,
    fontWeight: 'bold',
    textAlign: 'center',
    color: '#535B60',
    padding: 20
  },
  number: {
    fontSize: 60,
    fontWeight: 'bold',
    textAlign: 'center',
    color: '#535B60',
    padding: 20
  },
  plusButton: {
    backgroundColor: '#9FC4AD',
    width: 200,
    borderRadius: 10,
    margin: 10
  },
  minusButton: {
    backgroundColor: '#BAAAC4',
    width: 200,
    borderRadius: 10,
    margin: 10
  },
  buttonText: {
    fontSize: 40,
    fontWeight: 'bold',
    textAlign: 'center',
    color: '#535B60'
  }
});

class App extends Component {
  state = {
    raccoons: 0
  };

  addMore = () => {
    this.setState({
      raccoons: this.state.raccoons + 1
    })
  }
  removeOne = () => {
    if(this.state.raccoons !== 0){
      this.setState({
        raccoons: this.state.raccoons - 1
      })
    }
}

  render() {
    return (
      <View style={styles.container}>
      <Image style={styles.image} resizeMode='contain' source={require('./img/raccoon.png')} />
      <Text style={styles.question} >How many raccoons did you see last night?</Text>

      <Text style={styles.number}>{this.state.raccoons}</Text>

      <TouchableOpacity onPress={this.addMore} style={styles.plusButton} >
      <Text style={styles.buttonText}>PLUS</Text>
      </TouchableOpacity>

      <TouchableOpacity onPress={this.removeOne} style={styles.minusButton}>
      <Text style={styles.buttonText}>MINUS</Text>
      </TouchableOpacity>
      </View>
    )
  }
}

export default App;

First, replace the Button component with a TouchableOpacity component wrapped around a Text component. Pass the “buttonText” style to the Text and the “addMore” function to the TouchableOpacity. Next I wanted to differentiate the two buttons, so I created another style named “plusButton” and renamed “button” to “minusButton”, then passed them accordingly. I then changed the font size of the question and added padding and margin to some components to separate them. Here is what I was left with:

I’m not much of a designer but I am happy with the way the project came out but if there’s something you don’t like, play around with the styling. Adjust the font sizes, font color, background colors or spacing between components. There’s a lot you can do to make your app unique. You can change the image of the raccoon to something else, maybe a bird, or change the color scheme. There are a lot of options online to find royalty free images and color schemes.

In the next article, we will continue to work with this project. We will use more built in components and style them. For now, make sure you understand what was done in this article and if there’s something that doesn’t make sense visit the React Native documentation, https://facebook.github.io/react-native/.

Getting Started With React Native

React Native

In this article you will learn how to set up your computer to begin developing apps using React Native.

Before we begin, what is React Native? As stated on the official React Native website, https://facebook.github.io/react-native/, “React Native lets you build mobile apps using only JavaScript. It uses the same design as React, letting you compose a rich mobile UI from declarative components.” The site goes on to say, “With React Native, you don’t build a ‘mobile web app’, an ‘HTML5 app’, or a ‘hybrid app’. You build a real mobile app that’s indistinguishable from an app built using Objective-C or Java. React Native uses the same fundamental UI building blocks as regular iOS and Android apps. You just put those building blocks together using JavaScript and React.”

You can learn more by reading the documentation at https://facebook.github.io/react-native/.

One important thing to keep in mind, is that, although React Native allows you to develop iOS and Android apps, you will need to have a Mac computer to build an iOS application.

Setting Up Your Computer

Depending on your experience, skills and what you plan on doing, you may either want to develop with Expo or with the React Native CLI. What’s the difference?

Expo is the easiest and quickest way to get started and build simple apps. There is no need to use Xcode or Android studio, simply use the Expo CLI to develop your app and run it on your phone using the Expo client app.

React Native CLI, on the other hand, allows more flexibility and control. With it you can do things, such as, using third party packages that require you to run the command “react-native link”. It also allows you to go in and make changes to native iOS and Android code. But the installation process will vary depending on the operating system your computer is running. Window users be aware that you will not be able to build iOS projects because iOS development requires a Mac. On the other hand, Mac using will be able to develop for both iOS and Android.

I will be walking you though, both the Expo and React Native CLI installation. Let’s begin with Expo. If you prefer Reactive Native CLI, please skip ahead to the Reactive Native CLI installation section.

Expo Installation

To use Expo, you need to install Node. The fastest and easiest way to install Node is through the website. Head to https://nodejs.org and choose a version. LTS is more stable, more likely to work, and the recommended option. Current is the latest version of Node but may not work with React Native. Choose one, download it and follow the instructions to install. Node will also install npm. Using the Node website will work for both Mac and Window users.

Once installed you can check the version of Node by opening the Terminal or Command Prompt and type the following and then press the “Enter” key:

node -v

Node will also install npm, to check the version type:

npm -v

If you are unsure how to open Terminal or Command Prompt, here is how to do so:

To open the Terminal on a Mac, open the Applications folder, then the Utilities folder and click on Terminal. Or press “Command” and ‘space” keys to open Spotlight and search for “Terminal”, which will be under “Application” section.

To open the Command Prompt on Windows, search for cmd in the Start menu. Or press the “Windows” and “R” key to open the Run window and search for “cmd”.

Version used in this article:

Node version = v10.15.3 and npm version = 6.9.0

Next install the Expo CLI command line utility. Do so by typing the following into your Terminal or Command Prompt:

npm install -g expo-cli

The next step is not mentioned in the React Native documentation, but the Expo documentation states that you will need Git on your computer to create projects. The link to Expo’s installation documentation is located here, https://docs.expo.io/versions/latest/introduction/installation/.

 

You can download Git here, https://git-scm.com/downloads. Download the correct version for your computer.

Start the Git setup. The Mac and Windows installation process differ. The Windows setup offers much more options than the Mac setup. I am not a Windows user, so I left all the settings as default and installed. You may need to restart your computer afterwards.

 

(Git installation on Windows)

The final step is to install the Expo client app on your phone.

Download the Expo client app for iOS from the App Store, https://itunes.apple.com/app/apple-store/id982107779. Or search for “Expo Client” in the App Store.

Download the Expo client app for Android from the Google Play Store, https://play.google.com/store/apps/details?id=host.exp.exponent&hl=en_US. Or search for “Expo Client” in the Google Play Store.

Having an Expo account will open up a few more options, such as publishing projects to your Expo portfolio. You can create an Expo account through the app or through their website, https://expo.io/. This step is optional.

React Native CLI Installation

React Native CLI has a series of steps that will vary for Mac and Window users. I will start by guiding you through the steps for those using Mac, then for those using Windows.

Mac Installation

Start by installing Homebrew, head to https://brew.sh, copy the script and paste it into the Terminal.

Once installed, run the following command in the Terminal:

brew install node
brew install watchman

Installing Node will also install npm.

Next step is to install the React Native CLI by typing:

npm install -g react-native-cli

iOS Set Up

Let’s first start by downloading Xcode, which is necessary for iOS builds.

You will find Xcode at https://itunes.apple.com/us/app/xcode/id497799835?mt=12, click “View in Mac app store” to download and install. Or open the Mac App Store and search for “Xcode”.

Next, install Xcode Command Line Tools. Open Xcode and choose “Preferences…” from  the Xcode menu on the upper left corner of the screen. The General window will open, go to Locations and toward the bottom, install the Command Line Tools by selecting the latest version from the dropdown.

At this point you are ready to create your first React Native project but if you want to develop for Android too, please follow the following steps.

Android Set up

Let’s focus on downloading what’s needed for Android builds.

First thing to do is install the Java SE Development Kit (JDK). You can find it at http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html.

Next, install Android Studio, you can find it at https://developer.android.com/studio/index.html.

Once installed open Android Studio, the Android Studio Setup Wizard will open. Click “Next” and when asked to choose between “Standard” and “Custom” installation, pick “Custom”.

Click “Next” and choose the theme you would like, then click “Next”. At this point it will ask you to check the components you would like to download. According to the React Native documentation, check Android SDK, Android SDK Platform, Performance (Intel HAXM) and Android Virtual Device.

 

(I had Android Studios already install and that is why I got a warning at the bottom.)

Click “Next” and leave the Emulator settings on the recommended setting and click “Next”, then “Finish”.

There are a couple more steps left.

Open Android Studio and in the lower right side of the window, click Android Studio click on “Configure” and “SDK Manager”.

Select the “SDK Platforms” tab, make sure you have “Show Package Details” checked on the bottom right side of the window. Select Android 9.0 (Pie) and make sure Android SDK Platform 28, Intel x86 Atom_64 System Image and Google APIs Intel x86 Atom System Image are checked.

Then click on the “SDK Tools” tab, making sure “Show Package Details” is checked on the lower right side of the window. Look under “Android SDK Build-Tools 29-rc2”, make sure 28.0.3 is selected.

Now click “Apply”, accept the user agreements and install.

Last step is to add a few lines to your “.bash_profile”. Open up Terminal and type:

nano .bash_profile

Then add the following lines:

export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools

 

To save the changes simply press “Control” and “X”. You will be asked to save changes, hit “Y” and then “Enter” to exit.

You’re all set for iOS and Android development on your Mac.

Windows Installation

Begin by installing Chocolatey, which can be found at  https://chocolatey.org/install/. Copy the command under “Install with cmd.exe” and paste it into the Command Prompt.

 

 

To open the Command Prompt, search for “cmd” in your Start menu, right click on it and select “Run as administrator”. A pop up will open asking for permission, select “Yes”. Copy the command provided into the Command Prompt and install.

Ensure that it is installed by typing:

choco

This will return the version and a command for the help menu.

Then type:

choco install -y nodejs.install python2 jdk8

After that, it is time to install the React Native CLI by typing the following into the Command Prompt:

npm install -g react-native-cli

I noticed that when I tried to do this, I got an error saying “npm” was not a recognized command. Restart your computer, open cmd as an administrator and try again.

Next, install Android Studio. You can find it at https://developer.android.com/studio/index.html. Open Android Studio, the Android Studio Setup Wizard will open. Click “Next” and when asked to choose between “Standard” and “Custom” installation, pick “Custom”.

(This window, and a few of the following, are screenshots taken on a Mac.)

Click “Next” and choose the theme you would like, then click “Next”. At this point it will ask you to check the components you would like to download. According to the React Native documentation, check Android SDK, Android SDK Platform, Performance (Intel HAXM) and Android Virtual Device. Click “Next” and leave the Emulator settings on the recommended setting and click “Next”, then “Finish”.

(Ignore the warning. This image is a screenshot from my Mac and I had previously installed Android Studios.)

Open Android Studio and in the lower right side of the window, click on “Configure” and “SDK Manager”.

Select the “SDK Platforms” tab, make sure you have “Show Package Details” checked on the bottom right side of the window. Select Android 9.0 (Pie) and make sure Android SDK Platform 28, Intel x86 Atom_64 System Image and Google APIs Intel x86 Atom System Image are checked.

Then click on the “SDK Tools” tab, making sure “Show Package Details” is checked on the lower right side of the window. Look under “Android SDK Build-Tools 29-rc2”, make sure 28.0.3 is selected.

 

Next search for “Environment variables” in the Start menu, and select “Edit the system environment variables”. When the window opens, click on the “Advanced” tab and towards the bottom select the “Environment Variables”. Under “User variables for YOUR_USERNAME”, click “New” and add the following:

Variable name = “ANDROID_HOME”
Variable value = “c:\Users\YOUR_USERNAME\AppData\Local\Android\Sdk”

You can find the location of the SDK by looking in the “SDK Manager” settings of Android Studio.

 

Next select “Path” in the “User variables for YOUR_USERNAME” and select “Edit”. A new window will open, click “New” and add the following:

c:\Users\YOUR_USERNAME\AppData\Local\Android\Sdk\platform-tools

Close the “Edit environment variable”, “Environment Variables” and “System Properties” windows by clicking “Ok”.

You are all set! Let’s begin by creating an Expo project, if you decide to use only React Native, please skip ahead.

Creating Expo Project

From here on out I will be working on a Mac, the steps will be the same on Windows but I will not be using the Command Prompt. I will be using commands, such as “clear”, that will work in the Terminal but may not work in the Command Prompt.

Open up a new Terminal and head to the directory you wish to save the project in.

I like to save my projects onto my Desktop, so I will type:

cd Desktop

Once in the directory of your choice, type:

expo init FirstProject

“expo init” initializes a directory called “FirstExpoProject”. If you prefer to name the project something else, replace “FirstExpoProject” with the name of your choice.

There will be an option given to “Choose a template”, select “Blank” and press “Enter”.

Next, you are prompted to enter “The name of your app visible on your home screen”. I will type “FirstExpoProject” and press “Enter”.

Congrats! You created your first React Native app. To enter the folder type:

cd PROJECT_NAME

And the follow to start it:

expo start

Or

npm start

A new tab will open in your web browser, called the Expo Dev Tool. Depending on your computer this may take some time.

You will have a few options to view the app.

One way to view the app is to use the QR code. In the Terminal and Expo Dev Tool you will see a QR code. You can scan the code with the Expo app on Android or the iPhone’s camera.

Make sure your computer and phone are on the same network when the “Connection” in Expo Dev Tools is set to “LAN”. If you select “Tunnel”, then both devices can be on different networks.

Another way to view the app is to type “e” in the Terminal, allowing you to send an email or text message with a link to the app. You will have the same option in the browser.

And the final option I will discuss, is to open the app in the Android emulator or iOS simulator, which requires you to first install Android Studio and Xcode. If you want to do this, please look at the section titled “React Native CLI”.

Once you have it running it will look like this:

It’s now time to see what we created! You will need a text editor for this part and my personal preference is Visual Studio Code, which can be downloaded here https://code.visualstudio.com/. There are other options, such as Atom and Sublime, for example. Since I will be using Visual Studio Code, some of the following steps may differ if you are using a different editor.

Open Visual Studio Code, and open the “FirstExpoTutorial” project. On the left side of the editor you will see the “Explorer” section. If you do not see it, click on “View” at the top of the screen and then on “Explorer”.

In the “Explorer”, open up App.js file, this is where we will modify the code.

 

The first line of code imports the default export React from the module react.

The second line is importing components from React Native. React Native has a bunch of built in components and apis which you can see here, https://facebook.github.io/react-native/docs/components-and-apis.

Next comes the class App, which has the function render(), that returns JSX code, similar to HTML, and is exported.

The JSX consist of a View, a container that supports layout, and Text, a React component for displaying text. Replace the text between the <Text></Text> tags, with:

<Text>Hello World! Welcome to my new expo app!</Text>

Save the file and the app will reload with the new text.

The last block of code you will notice is the constant named styles. This is the styling that is passed to the View component and is similar to CSS styling.

Creating React Native Project

The steps to create a project using the React Native CLI are similar to Expo. Use the command “cd” to move directories. I will use the following command to move to the Desktop directory, but you can choose any directory:

cd Desktop

Once you are in the directory you wish to create the project in, type :

react-native init FirstRNProject

“react-native init” initializes a directory called “FirstRNProject”. You can choose to name your project something else.

During the initialization it may suggest that you use Yarn to speed it up. This is optional but if you want Yarn you can download it at https://yarnpkg.com/en/docs/install#mac-stable. There is a Homebrew option I will use on Mac, type the following in the terminal:

brew install yarn

In Windows either use the Installer or Chocolatey. To use Chocolatey, type the following into the Command Prompt as an administrator:

choco install yarn

Congrats! You created your first React Native app. Now it’s time to run the app. After creating the project, you may have noticed that there are instructions on how to run it. First thing to do is to enter the project folder by typing the following into the Terminal:

cd FirstRNProject

If you are on a Mac, you can run you iOS project two ways. One is to type the following into the Terminal:

react-native run-ios

This command will start building your app and will open it on the iOS simulator. Second way to run the project is to open the “YOUR_PROJECT_NAME.xcodeproj” file inside the “ios” folder of the React Native project. Xcode will open up, select the simulator and click on the run button at the top left side of the window.

This is how the app will look on the simulator:

If you are using Windows or Mac and want to run the app on Android, start by opening up Android Studios to start up the emulator before running the command in the Terminal.

Select “Open an existing Android Studio project” from the “Welcome to Android Studio” window.

Navigate to the directory where the project is located and the select the “android” folder inside and click “Open”. There may be a popup asking you to update the Android Gradle plugin. Don’t upgrade because it may cause the project not to work, I clicked “Don’t remind me again for this project”.

Before running the command in the Terminal, there is one last thing to do and that is to check the AVD Manager. Go to Tools in the top of the screen and click on “AVD Manager”. The Android Virtual Device Manager window will open. I have a device already set up using Android 9.0.

If you don’t see a device or want to create a new one, click on “Create Virtual Device”. Select the device you want and click “Next”. On the following screen select “Pie”, download if needed” and click “Next”.

Give the device a custom name or leave it as default and click “Finish”. Choose a device to run and click on the green play button under “Actions”.

Once the emulator is running, go back to the Terminal and inside the project you created run the following command:

react-native run-android

Here is how the project will look in the emulator:

It’s now time to see what we created! You will need a text editor for this part and my personal preference is Visual Studio Code, which can be downloaded here https://code.visualstudio.com/. There are other options, such as Atom and Sublime, for example. Since I will be using Visual Studio Code, some of the following steps may differ if you are using a different editor.

Open Visual Studio Code, and open the FirstTutorial project. On the left side of the editor you will see the Explorer section. If you do not see it, click on “View” at the top of the screen and then on “Explorer”.

Since the project was created with the React Native CLI, you will notice that this project has more folders than an Expo project. Two folders that stand out are the Android and iOS folders, which will give you access to native code.

In the Explorer, open up App.js file, this is where we will modify the code.

The first line of code, “import React from ‘react’”, imports the default export React from the module react.

The second line is importing components from React Native. React Native has a bunch of built in components and apis which you can see here, https://facebook.github.io/react-native/docs/components-and-apis.

The React Native project will then have a constant named “instructions”. What it does is determine which kind of phone that app is running on and will display text accordingly.

Next comes the class App, which has the function render(), that returns JSX code, similar to HTML, and is exported.

The JSX consist of a View, a container that supports layout, and a few Text, a React component for displaying text. Delete the bottom two, then replace the text between the <Text></Text> tags, with:

<Text>Hello World! Welcome to my new React Native app!</Text>

Save the file and if the text on the simulator/emulator does not change, simply reload the app. To do so on the iOS simulator press “Command” and “D” and click reload. In the Android emulator press “Command” and “M” if running it on Mac or “Control” and “M” on Windows.

The last block of code you will notice is the constant named styles. This is the styling that is passed to the View component and is similar to CSS styling.

Now What?

Congratulations! You have installed everything necessary to create a React Native project, started the project and modified the code. Take a look at the React Native documentation or Expo documentation and play around with the project. Add more text, change the background color, add an image or a button. This is just the beginning, in no time you will be creating amazing apps and publishing them for the world to see.