Building Mobile Apps with React Native
In this tutorial, we'll learn how to build mobile apps with opensource React Native. We'll see by example how to build a mobile applications, step by step, that fetches and displays news articles from a third-party REST API.
In this tutorial, we'll be building a news application to help you learn about the basics of React Native development process. Our mobile app will be cross-platform which means it can be used on both Android apps and iOS. We'll be using Expo for development which will allow us to initialize a new project and easily test it in a real mobile device.
What is React Native?
React Native is an open source SDK for building native mobile applications using JavaScript. It's based on React, a popular front-end library for building user interfaces using composable components created by Facebook.
Unlike the popular hybrid frameworks such as Ionic, React Native doesn't use a webview which means your mobile application is not a web application that has access to native device features like the case of Ionic but a native app that uses native components in both Android apps and iOS.
React Native is essentially a bridge that allows your JavaScript app to access native device features and user interface components.
Prerequisites
In this tutorial, we'll develop a mobile application from scratch using JavaScript and React Native so you'll need to have a few prerequisites before you can comfortably proceed with the next steps:
- Node.js and NPM installed on your system. You can install both of them from the downloads page of the official website. You can also refer to your system docs for the specific instructions on how to install Node on your system. A better way is to use NVM that allows you to install and manage multiple versions.
- Familiarity with JavaScript,
- Working knowledge of React and familiarity with the basic concepts like components, hooks, props, and state, etc.
You'll also need to register a free account with NewsAPI.org and note the API key.
News API is a simple and easy-to-use API that returns JSON metadata for headlines and articles live all over the web.
If you have the previous prerequisites, you are ready for the next steps of this tutorial.
Installing Expo CLI
Expo CLI is a command-line utility that allows you to use Expo tools. You can use it to create a new React Native project, develop and test your mobile app, build and publish your app to the App and Play Stores, etc.
Let's now install the Expo CLI. Open a new command-line interface and run the following command:
bash$ npm install -g expo-cli
$
Note: Please note that you may need to use
sudo
before your command in Linux or macOS to install npm packages globally or use a CMD with administrator access on Windows. if you get any EACCESS permission errors you can also just fix your npm permissions.
Wait for npm to install the CLI and let's proceed to the next step.
Creating a React Native Project
After installing the Expo CLI, let's use it to initialize our React Native project. Head back to your command-line interface and run the following command:
bash$ expo init react-native-example
$
You'll be asked to choose a template for your project, use the blank template and type a name for your application then wait for the CLI to generate the necessary files and install the packages from npm.
Next, navigate to your project's folder and run the local development server using the following commands:
bash$ cd react-native-example $ expo start
$$
This is a screenshot below of what you'll get in your terminal. The command starts the Metro bundler which bundles the JavaScript code of your application and Expo DevTools that allows you to debug your application. Depending on your development environment, you can either use an iOS simulator or an Android emulator or an actual mobile device to test your application. If you don't have a development environment with Java and Android Studio installed or a macOS with Xcode you can install the Expo app on your mobile device and scan the QR code as shown:
Image loading...
Go ahead and install the Expo app on your mobile device and scan the QR code in your terminal, you should be able to start your app on your mobile device. This is a screenshot:
Image loading...Next, open the App.js
file, you should find the following code that is responsible for rendering the user interface in the previous screenshot:
jsximport React from 'react'; import { StyleSheet, Text, View } from 'react-native'; export default function App() { return ( <View style={styles.container}> <Text>Open up App.js to start working on your app!</Text> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, });
We import React
from react
, next we import StyleSheet
, View
and Text
UI components from react-native
.
Next, we define and export a functional React component. This function returns the JSX code that renders the UI of our screen. JSX is an extension for JavaScript that allows you to write an XML-like markup in JavaScript.
The View
and Text
components are basic UI components for React Native apps. You can think of them as the <div>
and <p>
tags in HTML.
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, android.view
in Android, or <div>
in HTML. View
has support for the Flexbox layout by default, and supports styles and touch events.
Inside the View
component, we have a Text component which wraps the Open up App.js to start working on your app! text. When building React Native apps, you should always wrap the text with the Text
component which also supports styles and touch events.
React Native makes use of CSS written in JavaScript where CSS properties are defined using the camelCase. For example, we use backgroundColor
instead of background-color
.
All React Native components support a style
prop that you can use to assign styles to the component using either an inline JavaScript object or a reference to an object that encapsulates the styles.
You can define styles in plain JavaScript objects and you can also use the StyleSheet
API, provided by React Native, that enables you to define and manage multiple styles.
In our example code, we used the StyleSheet.create()
method to define reusable styles and we referenced them from the JSX code:
jsxconst styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, });
We create a container
object that contains the desired styles then assigned the styles to View
using the style
prop:
jsx<View style={styles.container}> </View>
Adding Multiple Screens in our Application
Now that we have explained the basics of React Native, let's modify our example code to create our application.
In this section, we'll see how to use conditional rendering to create multiple views or screens.
Please note that for complex scenarios, you'll need to use advanced navigation systems such as React Native Navigation library but in our case, since we'll only have two views in our application, we can use conditional rendering for implementing multiple screens.
Let's head to the App.js
file and define a Home()
component as follows:
jsxconst Home = () => { return ( <View style={styles.container}> <Text> This will be the home screen of our application. </Text> </View> ); }
Next, define a Loading
component as follows:
jsxconst Loading = () => { return ( <View style={styles.container}> <Text> Loading... </Text> </View> ); }
Next, change the App()
component as follows:
jsxexport default function App() { const [fetchingData, setFetchingDataState ] = React.useState(true); setTimeout(() =>{ setFetchingDataState(false); } , 1000); if (fetchingData){ return <Loading /> } else { return <Home /> } }
We use the useState()
hook to create a fetchingData
state variable that takes a boolean value and a setFetchingDataState()
method to update the value of the state variable.
The fetchingData
state variable has a first value of true
which means the <Loading />
component will be rendered first. After one second, the value of fetchingData
will be changed to false
via the setFetchingDataState()
method which will make the <Loading />
component to disappear and the <Home />
component will be rendered.
You can now go back to your mobile device and see these works. You don't need to restart your application since the development server will live-reload your app when you do any changes in the code.
This is a screenshot of the loading screen:
Image loading...And this is a screenshot of the home screen:
Image loading...Now if that works, let's see how to actually fetch news data from a third-party REST API.
How to Fetch Data in React Native
After seeing how to change between two screen views after an amount of time, let’s see how we can fetch data from a REST API. When data fetching is done we can then render the home screen.
React Native provides the Fetch API that allows you to consume REST APIs or fetch data from web servers.
In our <Loading>
component, we need to use the useEffect
hook to perform a side effect. In our case, it's fetching data from a REST API server.
Head back to the App.js
file and add the API_KEY
and apiUrl
variables as follows:
jsxexport default function App() { const API_KEY = "<PUT_YOUR_API_KEY>"; const apiUrl= `https://newsapi.org/v2/everything?q=comics&sortBy=publishedAt&apiKey=${API_KEY}`;
Note: Make sure to replace
<PUT_YOUR_API_KEY>
with your own API key from the News API.
Next, add the items
state variable for storing the news articles and initialize it with an empty array using the useState()
hook:
jsxexport default function App() { const API_KEY = "<PUT_YOUR_API_KEY>"; const apiUrl = `https://newsapi.org/v2/everything?q=comics&sortBy=publishedAt&apiKey=${API_KEY}`; const [items, setItems] = React.useState([]);
Next, call the fetch()
method in the useEffect()
hook to fetch data from the news API as follows:
jsxexport default function App() { const API_KEY = "<PUT_YOUR_API_KEY>"; const apiUrl = `https://newsapi.org/v2/everything?q=comics&sortBy=publishedAt&apiKey=${API_KEY}`; const [fetchingData, setFetchingDataState] = React.useState(true); const [items, setItems] = React.useState([]); React.useEffect(() => { fetch(apiUrl) .then((response) => response.json()) .then((data) => { return data.articles; }) .then(articles => { setItems(articles); setFetchingDataState(false); }) .catch(error => { console.error(error); }); }, []);
Now, let's pass the fetched articles to the <Home>
component using a data
property as follows:
jsxif (fetchingData){ return <Loading /> } else { return <Home data = { items }/> }
We have fetched data from the REST API and passed it to the home component, let's now modify the component to enable it to render the passed data via the data
prop. Change the Home
function as follows
jsxconst Home = ({data}) => { return ( <View> { data.map((item, index)=>{ return <Text key = {index}> { item.title } </Text> }) } </View> ); }
Inside the <View>
container, we call the JS map()
method to iterate over the data
array and display the title of each news article using a Text
component.
You can now head to your mobile phone to see your news data displayed before we further develop our app by using the FlatList
component to render the list of articles:
Using FlatList in React Native
React Native provides FlatList and SectionList for efficently rendering and working with lists.
Let's change our component to use a FlastList
.
Head back to the App.js
file and import the FlatList
component as follows:
jsimport { StyleSheet, Text, View, FlatList } from 'react-native';
Next, change the Home()
component as follows:
jsconst Home = ({data}) => { return ( <View style={styles.container}> <FlatList keyExtractor={(item, index) => index.toString()} data={ data } renderItem={({item}) => <Text> {item.title}</Text>} /> </View> ); }
Instead of rendering the title of the news article only, let's display other information like the description, URL and image. In the App.js
file, add the following function:
jsconst Item = ({ data }) => { return ( <View style={styles.itemContainer}> <Image style={styles.itemImage} source={{ uri: data.urlToImage }} /> <Text style={styles.itemTitle}> {data.title} </Text> <Text style={styles.itemDescription}> {data.description} </Text> <View style={styles.itemBtn}> <Button onPress={() => { console.log("Button pressed!") }} title="Read" /> </View> </View> ) }
Make sure you import Image
and Button
:
jsimport { Image, Button } from 'react-native';
Next, modify the Home()
component as follows:
jsconst Home = ({ data }) => { return ( <View style={styles.container}> <FlatList keyExtractor={(item, index) => index.toString()} data={data} renderItem={({ item }) => <Item data={item} />} /> </View> ); }
Next, we need to add the following styles to the styles
object:
jsconst styles = StyleSheet.create({ /* [...] */ itemContainer:{ borderWidth: 0, width: '100%', padding: 5 }, itemimage: draft: yes { height: 200 }, itemTitle:{ textAlign: "center", padding: 20, fontSize: 17, color: 'black', backgroundColor: 'white', }, itemDescription:{ fontSize: 17, padding: 10, color: 'black', backgroundColor: 'white', }, itemBtn:{ flexDirection: 'row', backgroundColor: 'white', } }
This is a screenshot of our application at this point:
Image loading...Now that we have created and styled the UI of our application, let's head to the next section.
Opening External URLs in React Native
During our development process we have added a button to enable users to open the news articles using a web browser for reading the full articles. Let's now see how to actually implement the button functionality.
Head to the App.js
file and import Linking
as follows:
jsimport { Linking } from 'react-native';
Next, define the following method:
jsconst readFullArticle = (url) => { Linking.openURL(url).catch((err) => console.error('An error occurred', err)); }
We simply call the openURL()
method of Linking
to open a URL in the default web browser of the mobile device.
Finally, you need to call this method in the Item
component as follows:
jsconst Item = ({ data }) => { return ( <View style={styles.itemContainer}> <Image style={styles.itemImage} source={{ uri: data.urlToImage }} /> <Text style={styles.itemTitle}> {data.title} </Text> <Text style={styles.itemDescription}> {data.description} </Text> <View style={styles.itemBtn}> <Button onPress={() => { readFullArticle(data.url); }} title="Read" /> </View> </View> ) }
Head back to your mobile device. You should be able to open the full article in the web browser.
You can read the docs for more information about what you can do with Linking
which allows you to interact with incoming and outgoing application links.
Conclusion
In this tutorial, we've introduced React Native and built a mobile application for Android and iOS from scratch using JavaScript and Expo CLI.
You can find the source code from this GitHub repository.