A comprehensive step by step tutorial on build Android/iOS Mobile Apps using Ionic 4, React.js, and Capacitor. In this tutorial, we will combine the Ionic 4 component in React.js React Hooks then build to the Native Android/iOS using Capacitor. If you are new to React.js and React Hooks you can read the documentation here. We are using Capacitor for the build to Android/iOS because Cordova did not support this combination of Ionic 4 and React.js.

Table of Contents:

The Android/iOS mobile apps that we will build is very simple. Just show the list of data that get from the REST API service using the Axios library. The REST API contains the nested array of JSON, so, using React Hooks will be very tricky. The Axios used by React.js and Vue.js to handle the HTTP request to the REST API.

So, you will learn how to create the new Ionic 4 application with the type of React, using Ionic 4 components in the React Hooks, populate nested JSON array in React Hooks, and build the native Android/iOS using Capacitor.

The generated Ionic 4 React application using React Hooks as the default

The following libraries, frameworks, tools, and modules are required for this tutorial:

Before we move to the main steps, check the Node.js version for the latest and recommended version. Type this command in the terminal or command line.

node -v npm -v



Create a New Ionic 4 React Application

Use the latest Ionic 4 version to create an Ionic 4 application with the type of React. Type this command in the terminal to update the Ionic CLI to the latest version.

sudo npm install -g ionic capacitor

Next, create a new Ionic 4 application with the type of React using this command.

ionic start ionic-react tabs --type=react

If you have a problem in installing the modules using `NPM` you can use Yarn for that. Go to the newly created Ionic 4 React Application then type this command to install the module.

cd ./ionic-react yarn install

Next, run the Ionic 4 React for the first time using this command.

ionic serve

Then the browser will open automatically to display this Ionic 4 React Screen.



Fetch Data from REST API and Display as List

As mention above, we will use Axios to fetch data from REST API. To install the Axios library/module, simply run this command.

npm install --save axios

Fetch data and display as a list will do in Ionic 4 React Tab 1. For that, open and edit `src/pages/Tab1.tsx` then replace all imports with these Ionic React IonList, IonItem, IonContent, IonHeader, IonTitle, IonToolbar, IonLabel, IonAvatar, IonLoading, React useState, useEffect, and Axios.

import { IonList, IonItem, IonContent, IonHeader, IonTitle, IonToolbar, IonLabel, IonAvatar, IonLoading } from '@ionic/react'; import React, { useState, useEffect } from 'react'; import './Tab1.css'; import axios from 'axios';

One of the problem while using React Hooks is JSON data that fetched from the REST API not easily can display to the Ionic 4 React component. It must return as a type which we will create an interface to handle that. Next, add these lines of interface codes before the `React.FunctionComponent`.

interface ITeam { name: string; code: string; } interface IMatches { num: number; date: string; time: string; team1: ITeam; team2: ITeam; } interface IRounds { name: string; matches: Array<IMatches>; }

As you see, there are three interfaces that related each other because we will fetch the nested arrays from the REST API. Next, add the `props` parameter to the Tab1 `React.FunctionComponent`.

const Tab1: React.FunctionComponent = (props) => { ... }

Next, declare the constant variables to handle data that fetched from the RESTful API and handle the loading spinner by adding these lines inside the top of Tab1 `React.FunctionComponent`.

const [data, setData] = useState<IRounds[]>([]); const [showLoading, setShowLoading] = useState(true);

To fetch data from the RESTful API using Axios, we have to do that by calling `useEffect` function that comes with React Hooks. Add these lines of `useEffect` function after the constant variable.

useEffect(() => { const fetchData = async () => { const result = await axios( 'https://raw.githubusercontent.com/openfootball/world-cup.json/master/2018/worldcup.json', ); setData(result.data.rounds); setShowLoading(false); }; fetchData(); }, []);

Add this function to go to details page included with parameter from this Tab1 page.

const showDetail = (data: any) => { let prop: any = props; prop.history.push({ pathname: '/tab1/details/' + JSON.stringify(data) }) }

As you see, the parameter data is all selected data from the list that converted to the string. Next, modify the Ionic 4 React component to display the list of data that contains the nested JSON arrays.

return ( <> <IonHeader> <IonToolbar> <IonTitle>World Cup 2018</IonTitle> </IonToolbar> </IonHeader> <IonContent> <IonLoading isOpen={showLoading} onDidDismiss={() => setShowLoading(false)} message={'Loading...'} /> <IonList> {data.map((round, idx) => ( <IonItem key={idx} onClick={() => { showDetail(round) }}> <IonAvatar slot="start"> <img src="assets/imgs/ball.png" alt="ball" /> </IonAvatar> <IonLabel> <h2>{round.name}</h2> {round.matches.map((im, idx2) => ( <p key={idx2}> <span>{im.date} {im.time}: {im.team1.name} vs {im.team2.name}</span> </p> ))} </IonLabel> </IonItem> ))} </IonList> </IonContent> </> );



Display the Details of Data

We will use existing Details page that linked to the Tab2. For that, we have to modify the Details page and Tabs to move the Details page linked to the Tab1. Open and edit `src/App.tsx` then modify the Ionic 4 React `IonRouterOutlet` to be like this.

<IonRouterOutlet> <Route path="/:tab(tab1)" component={Tab1} exact={true} /> <Route path="/:tab(tab1)/details/:data" component={Details} /> <Route path="/:tab(tab2)" component={Tab2} exact={true} /> <Route path="/:tab(tab3)" component={Tab3} /> <Route exact path="/" render={() => <Redirect to="/tab1" />} /> </IonRouterOutlet>

Now, the Details page is part of the Tab1 with the additional parameter of data that send from the Tab1 list of data. Next, make a little title and icon modification of the Tabs by modifying the Tabs codes.

<IonTabBar slot="bottom"> <IonTabButton tab="schedule" href="/tab1"> <IonIcon icon={aperture} /> <IonLabel>Matchdays</IonLabel> </IonTabButton> <IonTabButton tab="speakers" href="/tab2"> <IonIcon icon={apps} /> <IonLabel>Tab Two</IonLabel> </IonTabButton> <IonTabButton tab="map" href="/tab3"> <IonIcon icon={send} /> <IonLabel>Tab Three</IonLabel> </IonTabButton> </IonTabBar>

Next, open and edit the `src/pages/Details.tsx` then replace all imports with these.

import React, { useState, useEffect } from 'react'; import { IonBackButton, IonButtons, IonHeader, IonToolbar, IonTitle, IonContent, IonGrid, IonRow, IonCol, IonLabel, IonList, IonItem } from '@ionic/react';

Add the `props` param to the Details `React.FunctionComponent`.

const Details: React.FunctionComponent = (props) => { ... }

Declare the variables to convert `props`, `match`, and `params.data` as the `any` types. This method is different than the previous method in the list of data that convert a JSON array to the interface.

let prop: any = props; let match: any = prop.match; let data: any = JSON.parse(match.params.data);

Next, we have to extract the data from params to the Ionic 4 React components.

return ( <> <IonHeader> <IonToolbar> <IonButtons slot="start"> <IonBackButton defaultHref="/tab1" /> </IonButtons> <IonTitle>{data.name}</IonTitle> </IonToolbar> </IonHeader> <IonContent> {data.matches.map((m: any, idx: number) => ( <IonList key={idx} lines="none"> <IonItem> <IonLabel> <IonGrid> <IonRow> <IonCol><p>{m.date}</p></IonCol> </IonRow> <IonRow> <IonCol>{m.stadium.name}, {m.city}</IonCol> </IonRow> <IonRow> <IonCol><h2>{m.group}</h2></IonCol> </IonRow> <IonRow> <IonCol size="5"><b>{m.team1.name} ({m.score1})</b></IonCol> <IonCol size="2">vs</IonCol> <IonCol size="5"><b>({m.score2}) {m.team2.name}</b></IonCol> </IonRow> <IonRow> <IonCol> {m.goals1.map((g1: any, gidx1: number) => ( <p key={gidx1}>{g1.name} `{g1.minute}</p> ))} </IonCol> <IonCol> </IonCol> <IonCol> {m.goals2.map((g2: any, gidx2: number) => ( <p key={gidx2}>{g2.name} `{g2.minute}</p> ))} </IonCol> </IonRow> </IonGrid> </IonLabel> </IonItem> </IonList> ))} </IonContent> </> );



Run and Test The Ionic 4 React App to the Device using Capacitor

Before installing the Capacitor, we have to build the Ionic 4 React application first by type this command.

ionic build

Next, add the Capacitor Android platform using this command.

ionic capacitor add android

Next, type this command to build and open the Android Studio.

ionic capacitor run android

Now, you can run the Ionic 4 React application to the Android Device using Android Studio. And here the Ionic 4 React application looks like in the Android device.









Next, to run in the iOS device type this command first.

ionic capacitor add ios

If you get the error as below.

✖ Updating iOS native dependencies with "pod install" (may take several minutes): ✖ update ios: [error] Error running update: [!] Unknown installation options: disable_input_output_paths.

To fix that error, update the Cocoapods first then remove the `ios` folder before running again Capacitor platform adds.

sudo gem install cocoapods -n /usr/local/bin rm -rf ios/ ionic capacitor add ios

Next, open the XCode using this command.

ionic capacitor open ios

After some setting for your Apple Account, you can run the iOS application inside your XCode to your iPhone device. Here's what we have in our iPhone device.









That it's, the Build Android/iOS Mobile Apps using Ionic 4 React.js Capacitor. You can find the full working source code from our GitHub.

We know that building beautifully designed Ionic apps from scratch can be frustrating and very time-consuming. Check Ionic 4 - Full Starter App and save development and design time. Android, iOS, and PWA, 100+ Screens and Components, the most complete and advance Ionic Template.

That just the basic. If you need more deep learning about Ionic, Angular, and Typescript, you can take the following cheap course:

Thanks!