React native tutorial & example
Throughout this tutorial, you’ll learn to create your first React Native example app step by step by emphasizing basic theory and practice.
We’ll make use of React Native v0.6 (released in 2019), which is the latest version at the time of writing this tutorial.
What we'll be building in this React Native tutorial?
We'll be building a simple news app example that allows you to read and save news in the local storage for reading them later.
We’ll be using the news API from NewsAPI.org, register for an account and you’ll recieve an API key, note it and let’s continue.
What we'll be learning in this React Native tutorial?
In this React Native tutorial, we will teach you about the following topics:
- How to scaffold a React Native project,
- How to create a view in React Native by composing predefined UI components and Flexbox layout,
- How to implement navigation in your React Native app,
- How to style the UI,
- How to fetch data from REST API servers,
- How to get user input in React Native,
- How to respond to touch events in React Native,
- How to display images in React Native, etc.
What're the Prerequisites of this React Native tutorial?
In order to follow this React Native tutorial, you will need to have some prerequisites:
Familiarity with modern JavaScript/ES6 features: React Native is based on React which is a JavaScript library for building UIs, so you will need to be familiar with JavaScript and the latest ES6 features such as imports, exports and arrow functions.
React basics: You will need to be familiar with
- Components,
- State and properties,
- React Hooks,
- JSX: JSX is a powerful syntax extension that allows you to write your UI code with XML-like syntax and JavaScript., etc.
Node.js and NPM: We’ll be using React Native CLI for generating and working with our project which is built on to of Node.js, so you will need to have Node.js 8.3+ and NPM installed on your system. You can refer to the official docs for how to install Node.js using a package manager.
JDK 8+ and Android Studio installed on your system for Android development.
The
ANDROID_HOME
environment variable set to the path of your Android SDK.
On Ubuntu, you can add Android SDK to your PATH
by adding the following lines to the ~/.bash_profile
or ~/.bashrc
configuration files:
export ANDROID_HOME=$HOME/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
We also added the tools/bin
and platform-tools
folder to the PATH
variable to be able to run various utilities like adb
from any folder. Next, run the following command:
$ source ~/.bashrc
How to run an Android Emulator
You can test your React Native app in a real device or better yet an emulator. Make sure you have created an Android Virtual Device in your system. Next, check the names of the installed AVDs using the following command in your terminal:
$ emulator -list-avds
For example, I have the following virtual device installl:
Pixel_2_XL_API_28
Next, you need to run the following command to start your emulator with a chosen AVD:
$ emulator -avd Pixel_2_XL_API_28
Editing the code with Visual Studio Code
This is not a requirement and you can use your prefered IDE but in this React Native tutorial we’ll be use Visual Studio Code. It has great support for JavaScript and you can easily install it from the official website.
For iOS development
You can also built your React Native app for iOS provided that you are using a macOS, you only need to get a free iOS developer account.
Note: To deploy the app to the iOS App Store, you will need to get a license with $99/year.
For development, you will need to install Xcode from the official Xcode website.
Note: Xcode includes the Xcode IDE, the iOS simulators, and the iOS SDK. ****
Generate your React Native project
If you have the previous prerequisites, let’s get started by generating a new React Native project using React Native CLI.
Head over to a new terminal and run the following command to run the React Native CLI using the npx
command:
$ npx react-native init firstapp
Note: Thanks to the npx tool, you don’t need to install React Native CLI. You can run directly from npm.
We used the init
command of React Native CLI to create a project called firstapp.
Next, you need to navigate inside your React Native project and run the Metro Bundler using the following commands:
$ cd firstapp
$ react-native start
Metro is a bundler for JavaScript and React Native created by Facebook for compiling the React Native code.
Next, let’s leave Metro running and open a new terminal where you need to run the following commands to build and start your React Native application in the Android emulator you started earlier:
$ cd firstapp
$ react-native run-android
The run-android
command will build and run the app in the Android virtual device.
Note: For iOS, you will need to use the
react-native run-ios
command to build and run your app.
If your React Native app is successfully built, you’ll see a BUILD SUCCESSFUL message in your terminal and your app will be started in the Android emulator:
This is a screenshot of our app running inside an Android emulator:
Congratulations, you have started your first React Native app in your Android emulator. Now, let’s start writing the code.
If you have VS Code installed, head back to your previous terminal and run the following code from your project’s folder to open your it in VS Code:
$ code .
If you do any changes in your code, they will be live reloaded in your Android emulator so you don’t need to restart your app again.
Understanding the structure of your React Native project
After running our React Native app and opening the project in our IDE, let’s understand the structure of our project.
The project has the typical folders and configuration files for a Node.js project like the package.json
and package-lock.json
files and the node_modules
folder. We also have these files and folders:
babel.config.js
: The configuration file for Babel (A compiler and transpiler for JavaScript)metro.config.js
: The configuration file for Metro, a JavaScript bundler for React Native,app.json
: configures parts of our app that don’t belong in code. See this article.watchman.config
: The configuration file for Watchman, a file watch service,.flowconfig
: The configuration file for Flow, a static type checker for JavaScript,.eslintrc.js
: The configuration file for ESLint, a JavaScript and JSX linter (a tool for code quality),.buckconfig
: The configuration file for Buck, a build system created by Facebook,.gitignore
and.gitattributes
: ignores all files in version control that should be unique to each development machine,android
: The folder for the Android project,ios
: The folder for the iOS project,__tests__
: The folder for tests,App.js
: The main component in our React Native app,index.js
: The main file of our application where the components are registered.
That’s it. We have seen the most important files and folders of our React Native project generated using the official CLI.
Create a React Native screen
After understanding the basic structure of our project, let’s now see how we can use the prebuilt React Native UI components to create a view.
We already have an App.js
file which contains the code of the root React component in our app. So go ahead and open the App.js
file in your code IDE, and remove the existing code then add the following code instead:
import React from 'react';
import {
View,
Text,
} from 'react-native';
const App = () => {
return (
<View style=>
<Text>Hello, world!</Text>
</View>
);
};
export default App;
We first import React
from react
, next we import the View and Text components from react-native
.
Next, we create a functional React component called App
using the ES6 arrow syntax. This function returns the JSX code that describes the UI of our screen.
The View
and Text
components are basic UI components that can be considered as the equivalents to the <div>
or <span>
and <p>
elements in HTML.
Finally, we export the App function so it can be imported from the other files.
After saving the file, go to your Android emulator and press R twice in your keyboard to reload your app. You should get the following UI:
The previous JSX code created an empty screen with a Hello, world! text at the center.
JSX is an extension for JavaScript that allows you to write HTML-like markup in JavaScript.
Note: You can think of JSX as a template language with JavaScript syntax.
You can also include JavaScript code inside JSX using curly braces { }
.
The React Native View
Component
In our App
component, we used the View
component to create a container for our text
View is a fundamental React Native component for creating a UI. It’s simply a container which is equivalent to a native view such as UIView
in iOS, or android.view
in Android.
You can nest View components to create complex layouts and add zero or multiple children inside a View.
View supports the Flexbox layout by default, can have styles and can listen for touch events.
The React Native Text
Component
Inside the View
container, we used a Text component which wraps our Hello World text.
In React Native, you have to use a Text component if you want to display text in the UI. It supports nesting, styling, and touch handling.
For example, we could write our previous component without the <View>
component and it will still work:
const App = () => {
return (
<Text>Hello, world!</Text>
);
};
But we can’t add text without the <Text>
component. For example, if you write the following code:
const App = () => {
return (
<View style={ { flex: 1, justifyContent: "center", alignItems: "center" } }>
Hello, world!
</View>
);
};
You will get an Invariant Violation error with the Text strings must be rendered within a <Text>
component message:
Styling the UI in React Native
At this point of our React Native tutorial, we have seen how to create a basic screen using the View and Text components. Let's now see how to style our simple UIs using CSS written in JavaScript. The CSS properties are defined using the camelCase instead of hyphens. For example, you need to use backgroundColor
instead of background-color
.
All the React Native components like View and Text can have a style
prop in which you can provide styles for the component using an inline JavaScript object or a reference to a JavaScript variable that contains the styles.
You can also provide an array of styles with the last style has precedence which can be used for emuating style inheritance which doesn't exist in React Native.
In our previous example, we supplied some inline styles using the style
prop which allowed us to center the text in our view:
<View style={ { flex: 1, justifyContent: "center", alignItems: "center" } }></View>
Adding styles in React Native with StyleSheet
React Native provides a StyleSheet
API that allows you to define and manage multiple styles in seprate places of files instead of adding them in your JSX code.
You simply need to call the StyleSheet.create()
method for defining reusable styles in one place/fie and reference them from your JSX code.
Note: In React Native, styles don’t cascade, but you can emulate cascading by re-using the same style object in the parent and chidren components.
At this point of our React Native tutorial, we have added some inline styles to our View component to center our Hello World text which is fine for our simple example but for the sake of learning best practices, let's take the inline styles from the JSX and define them in their own object using the StyleSheet.create()
method.
Head over to your code IDE, locate the App.js
file and start by importing StyleSheet
as follows:
import {
StyleSheet,
} from 'react-native';
Next, in the same file, add a styles
variable and add your styles using the StyleSheet.create()
method as follows:
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center"
}
});
We can now use the container
reference to apply our styles to any React Native component.
Next, apply the styles to View
component as follows:
const App = () => {
return (
<View style={styles.container}>
<Text>
Hello, world!
</Text>
</View>
);
};
You can also pass an array instead of one object to the style
prop:
const App = () => {
return (
<View style={ [styles.container] }>
<Text>
Hello, world!
</Text>
</View>
);
};
Note: Fo bigger apps, you can also add styles in separate files and import them using the
import
statement so you can reuse them in multiple views.
Again for the sake of learning the best practices, let’s define styles in a separate file in our simple tutorial example.
First, let's start by creating a new styles.js
file. Head back to your terminal and run the following command from your project's folder:
$ touch styles.js
Next, add the following code in the styles.js
file:
import {
StyleSheet,
} from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center"
}
});
export default styles;
We import StyleSheet
from react-native
and we call the create()
method to create a bunch of styles referenced by container
. We also need to export the styles
object so we can import it from the other JS files.
Next, you need to import the styles
object in your App.js
file as follows:
import styles from './styles';
const App = () => {
return (
<View style={ [styles.container] }>
<Text>
Hello, world!
</Text>
</View>
);
};
Building layouts in React Native with Flexbox
Ath this point of our React Native tutorial, we have created a basic screen using some fundamental UI components such as View and Text and we have seen how to define styles and apply them using the style
prop. We have also seen how to build a basic layout using Flexbox, let's now see more details about Flexbox.
Flexbox is the default layout for buiding UIs in React native. It's quite similar how it works in CSS except that the flexDirection
defaults to column
instead of row
, and the flex
parameter supports only a single number (a proportion of the available space).
In Flexbox, items are laid out horizontally or vertically (default) depending on the value of the flexDirection
property (row
| column
| row-reverse
| column-reverse
).
Flex
The flex
property is designed to specify a proportion of the available space (vertical or horizontal depending on flexDirection
) to a child element.
Note: You don’t need to add
display: flex
to a container to make it a flex container. Elements are by default flex containers.
You can also use properties like justifyContent
and alignItems
to align items either on the X-axis or the Y-axis.
Justifying Content
You can use the [justifyContent](https://facebook.github.io/react-native/docs/layout-props#justifycontent)
property to define how to align items in the main axis of a container. The main axis can be either the X-axis or the Y-axis depending on the value of flexDirection
which means:
- When
flexDirection
is set tocolumn
,justifyContent
will align items vertically, - When
flexDirection
is set torow
,justifyContent
will align items horizontally,
You can align items in many ways:
flex-start
(default): Align the items to the start of the container,flex-end
: Align the items to the end of the container,center
: Align the items in the center of the container,space-between
: Align the items across the main axis of the container with equal space between them.space-around
: Align the items across the main axis of the container, the remaining space will distributed around all items i.e to the beginning of the first child and end of the last child.
Aligning Items
You can use the [*alignItems*](https://facebook.github.io/react-native/docs/layout-props#alignitems)
property to specify how to align items along the cross axis of the container.
Align items is similar to justifyContent
but it aligns items according to the cross axis.
It takes the following values:
stretch
(default): Stretch children of a container to match theheight
of the container's cross axis.flex-start
Align children of a container to the start of the container's cross axis.flex-end
Align children of a container to the end of the container's cross axis.center
Align children of a container in the center of the container's cross axis.baseline
Align children of a container along a common baseline. Individual children can be set to be the reference baseline for their parents.
Note: You can use this playground to visually play with Flexbox.
Equipped with this basic information about Flexbox, let’s understand our previous snippet and improve it:
container: {
flex: 1,
justifyContent: "center",
alignItems: "center"
}
This is the style object applied to the <View>
component.
We used the flex
property to assign the available space to the container <View>
. This means it will span all the viewport since we only have one <View>
component.
We used the justifyContent
property with a center
value to center the children of the <View>
component vertically and the alignItems
property set to center
to center the children of the <View>
horizontally.
This makes the Hello, world! text (wrapped within the <Text>
component) vertically and horizontally centered in our application:
Adding images in React Native
Images are important in most apps, let's see how to add a background image in our React Native tutorial.
Let’s add a background image to our previous screen.
Since the previous screen is the only screen in our example app, let's make it the welcome/splash screen of our app that shows an image with the name of our app.
Head over to your IDE, change the App
component to show the name and description of our app.
In your App.js
file, import <ImageBackground>
as follows:
import {
View,
Text,
Button,
ImageBackground,
} from 'react-native';
Next, change the App
component as follows:
const App = (props) => {
return (
<View style = { styles.container } >
<ImageBackground style= { styles.backgroundImage } source= >
<View style= { styles.logoContainer }>
<Text style = { styles.logoText }>
Newzzz
</Text>
<Text style = { styles.logoDescription }>
Get your doze of daily news!
</Text>
</View>
</ImageBackground>
</View>
);
}
Let's also add some styles for the new elements. Go to the styles.js
file and add the following styles:
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "orange"
},
logoContainer:{
alignItems: "center",
},
logoText: {
fontSize: 24,
fontWeight: '600',
color: 'white'
},
logoDescription:{
fontSize: 15,
fontWeight: '600',
color: 'white'
},
backgroundImage:{
flex: 1,
width: '100%',
height: '100%',
justifyContent: "center",
alignItems: "center",
opacity: 0.7
}
});
This is the screenshot of our view:
Creating multiple React Native screens
At this point of our React Native tutorial, we have created a basic splash screen with some text and a background image that can be considered as a welcome screen of our app. Let’s create another screen that will be used to render the news headlines from the news REST API.
In the same App.js
file, define a HomeScreen()
function as follows:
const HomeScreen = () => {
return (
<View>
<Text>
Here, will be rendered our news.
</Text>
</View>
);
}
Before tacking React Native navigation, let's see how we can use conditional rendering to create and change between multiple views in simple example apps.
First, change the name of the original App
component to SplashScreen
. Now we have two components: SplashScreen
and HomeScreen
.
Next, define a new App()
function as follows:
const App = () => {
const [loading, setLoading ] = useState(true);
setTimeout(() =>{
setLoading(false);
} , 1000);
if (loading){
return <SplashScreen />
} else {
return <HomeScreen />
}
};
We used the useState
hook to define a loading
state variable so you also need to import the useState()
method:
import React, { useState } from 'react';
The laoding variable has an initial value of true
which means the <SplashScreen />
component will be rendered. After one second, the value of loading will be false
which will cause the <SplashScreen />
to disappair and <HomeScreen />
will be rendered instead.
This is just for the sake of showing how conditional rendering can be used to create multiple views. We'll see later in this React Native tutorial how we can use a real navigation system to implement mutiple views with more control and features.
Fetching data in React Native
Instead of switching between the two views based on time, let’s see how we can fetch data from a remote REST API before displaying the home screen. This is a more realistic use case!
In React Native, you can use the Fetch API for calling REST APIs or getting data from web servers.
In a functional React components, we don't have life-cycle methods so we need to use the useEffect
hook for performing side effects.
In the App.js
file, import the useEffect()
method as follows:
import React, { useState, useEffect } from 'react';
Next, define the API_KEY
and URL
constants as follows:
const App = () => {
const API_KEY = "<YOUR_API_KEY_HERE>";
const URL = `https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=${API_KEY}`;
Note: You need to replace
<YOUR_API_KEY_HERE>
with your API key from the News API.
Next, define the articles
variable for storing the articles and initialize it with an empty array:
const [articles, setArticles] = useState([]);
Next, call the fetch()
API in the useEffect()
method to get data from the news API:
useEffect(()=>{
fetch(URL)
.then((response) => response.json())
.then((responseJson) => {
return responseJson.articles;
})
.then( articles => {
setArticles(articles);
setLoading(false);
})
.catch( error => {
console.error(error);
});
} , []);
Also, finally we need to pass the articles
variable to the <HomeScreen>
component using a custom articles
property as follows:
if (loading){
return <SplashScreen />
} else {
return <HomeScreen articles = { articles }/>
}
As you can guess, the HomeScreen component doesn't actually know about any prop called articles
so we need to modify our component to render the items passed via the articles
prop:
const HomeScreen = (props) => {
return (
<View>
{
props.articles.map((article, index)=>{
return <Text key = {index}>
{ article.title }
</Text>
})
}
</View>
);
}
We simpy render each news article using a Text
component.
This not the most efficient method of rendering lists. In the next section of our React Native tutorial, we’ll learn how to use the FlatList
component to render lists.
Rendering lists in React Native
In React Native, you can use FlatList or SectionList for rendering lists.
Let's change our previous code to use a flast list. In the App.js
file, start by importing
the FlatList
component as follows:
import {
FlatList
} from 'react-native';
Next, update the HomeScreen
component as follows:
const HomeScreen = (props) => {
return (
<View>
<FlatList
keyExtractor={(item, index) => index.toString()
data={ props.articles }
renderItem={({item}) => <Text> {item.title}</Text>}
/>
</View>
);
}
We use the data prop to pass the articles to the list and the renderItem to tell React Native how to render each item of our data. In our example, we simply render the title of each item using the Text
component:
We can also render complex components as the list item. Let's first create a custom component that dispays the title and description of a news article.
In the App.js
file, define the ArticleItem
component as follows:
const ArticleItem = ({article}) => {
const { description, title } = article;
return (
<View>
<Text>
{ title }
</Text>
<Text>
{ description }
</Text>
</View>
)
}
The component accept an article
prop and render the title and description of the article with Text components.
Using buttons in React Native
React Native provides a button component and a set of "Touchable" components for implmenting custom buttons if the default one is not enough.
We need to be able to open a news article or save it for reading later in our app so let's change our ArticleItem
component as follows:
const ArticleItem = ({article}) => {
const { description, url, urlToImage } = article;
return (
<View>
<Image source= />
<Text>
{ title }
</Text>
<Text>
{ description }
</Text>
<Button onPress = { () => { console.log("Button pressed!")} } title="Open" />
<Button onPress = { () => { console.log("Button pressed!") } } title="Read later" />
</View>
)
}
For now, when your press the buttons you will only see Button pressed! message in the terminal if you are listenning for logs. We’ll learn how to implement the actual features using the Linking
and AsyncStorage
modules in our React Native tutorial in the next sections.
We also added an <Image>
component to display the image of the article.
Next, let's wire the ArticleItem
component to the FlatList
component in HomeScreen
function as follows:
const HomeScreen = (props) => {
return (
<View>
<FlatList
data={ props.articles }
renderItem={({item}) => <ArticleItem article = { item }/>}
/>
</View>
);
}
This is our UI at this point:
Unlike what's expected the images of the articles don’t appear!
To solve this issue, we need to add a height to the Image component. Head over to the styles.js
file and add the following styles:
const styles = StyleSheet.create({
/* [...] */
articleContainer:{
borderWidth: 0,
width: '100%',
padding: 5
},
articleImage: {
height: 200
},
articleTitle:{
textAlign: "center",
padding: 20,
fontSize: 17,
color: 'black',
backgroundColor: 'white',
},
articleDescription:{
fontSize: 17,
padding: 10,
color: 'black',
backgroundColor: 'white',
},
articleBtns:{
flexDirection: 'row',
backgroundColor: 'white',
},
});
Next, you need to apply the styles to their components:
const ArticleItem = ({article}) => {
const { title, description, url, urlToImage } = article;
return (
<View style = { styles.articleContainer }>
<Image style={ styles.articleImage } source= />
<Text style= { styles.articleTitle }>
{ title }
</Text>
<Text style = { styles.articleDescription }>
{ description }
</Text>
<View style = { styles.articleBtns}>
<Button onPress = { () => { console.log("Button pressed!")} } title="Open" />
<Button onPress = { () => { console.log("Button pressed!") } } title="Read later" />
</View>
</View>
)
}
Now, we have a much better UI:
Tutorial wrap-up
Throughout this React Native tutorial for the latest v0.6 released in 2019, we have created a simple example mobile app for Android and iOS using the fundamental concepts in React Native.
-
Date: