How can I find the best iOS developers in New Jersey?

Mobile App Development Services India, USA | Top Mobile and Tablet App Developers India

CMARIX is a leading technology Outsourcing company with CMMi level 3, ISO 27001, ISO 9001:2015 certifications in India and US that specialize in, Enterprise Software, Mobile Apps and Custom Web Application Development with clients across the globe.

CMARIX is a leading technology Outsourcing company with CMMi level 3, ISO 27001, ISO 9001:2015 certifications in India and US that specialize in, Enterprise Software, Mobile Apps and Custom Web Application Development with clients across the globe.

React Native Tutorial: SQLite Offline Android/iOS Mobile App

React Native Tutorial: SQLite Offline Android/iOS Mobile App

React Native Tutorial: SQLite Offline Android/iOS Mobile App

Table of Contents:
  • Install React App Creator and Create App
  • Add Navigation Header and required Screen
  • Install and Configure React Native SQLite Storage
  • Show List of Product
  • Show Product Details and Delete Product
  • Add Product
  • Edit Product
  • Run and Test React Native and SQLite Offline Mobile App

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

  • Install React App Creator and Create App
  • Add Navigation Header and required Screen
  • Install and Configure React Native SQLite Storage
  • Show List of Product
  • Show Product Details and Delete Product
  • Add Product
  • Edit Product
  • Run and Test React Native and SQLite Offline Mobile App

Before start to the main steps, make sure that you have installed Node.js and can run npm in the terminal or command line. To check the existing or installed Node.js environment open the terminal/command line then type this command.

node -v
v10.15.1
npm -v
6.8.0
yarn -v
1.10.1

1. Install React App Creator and Create App

The Create React Native App is a tool for creating a React Native App. To install it, type this command in your App projects folder.

sudo npm install -g react-native-cli

Then create a React Native App using this command.

react-native init reactOffline

That command will create a React Native app then install all required modules. The app or project folder will contain these folders and files.

Next, go to the newly created React App folder.

cd reactSqlite

To run on iOS device or simulator run this command.

react-native run-ios

The simulator will open along with the new terminal window. Go to the project folder from the new terminal window then run this command.

react-native start

Right after iOS build success and React Native started, you will see this view in the iOS Simulator.

To run on Android device or simulator, make sure ADB detected the device.

adb devices
List of devices attached
J8AXGF0194047T6    device

Next, type this command to run on the Android device or simulator.

react-native run-android

It will open the new terminal windows. Just go to the project folder then type this command.

react-native start

You will see this app in your Android device.

Sometimes, if running React Native app faster than starting React-Native Javascript bundler you see this red-screen of error.

No bundle URL present.

Make sure you’re running a packager server or have included a .jsbundle file in your application bundle.

RCTFatal
__28-[RCTCxxBridge handleError:]_block_invoke
_dispatch_call_block_and_release
_dispatch_client_callout
_dispatch_main_queue_callback_4CF
__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
__CFRunLoopRun
CFRunLoopRunSpecific
GSEventRunModal
UIApplicationMain
main
start
0x0

Don’t worry, just start the Metro Bundler in the newly opened terminal window after you go to the project folder. After Metro Bundler started completely, refresh the React Native app on your device or simulator. In iOS Simulator you will see this error after refresh.

Attempting to reload bridge before it's valid: <RCTCxxBridge: 0x7ff34bc00510>. Try restarting the development server if connected.

-[RCTCxxBridge reload]
&nbsp; &nbsp; RCTCxxBridge.mm:986
-[RCTRedBox reloadFromRedBoxWindow:]
-[RCTRedBoxWindow reload]
-[UIApplication sendAction:to:from:forEvent:]
-[UIControl sendAction:to:forEvent:]
-[UIControl _sendActionsForEvents:withEvent:]
-[UIControl touchesEnded:withEvent:]
-[UIWindow _sendTouchesForEvent:]
-[UIWindow sendEvent:]
-[UIApplication sendEvent:]
__dispatchPreprocessedEventFromEventQueue
__handleEventQueueInternal
__handleEventQueueInternal
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
__CFRunLoopDoSources0
__CFRunLoopRun
CFRunLoopRunSpecific
GSEventRunModal
UIApplicationMain
main
start
0x0

Just reload again the React Native app, you will get your React Native app running.

2. Add Navigation Header and required Screen

Above generated React Native App just show blank app with plain text. Now, we will show you how to add the Navigation Header and Home Screen for your app. So, it will look like the Native App. In the terminal or command line, type this command to install React Navigation module and don’t forget to stop the running Metro Bundler before installing the modules.

yarn add react-navigation --save
yarn add react-native-gesture-handler --save
react-native link react-native-gesture-handler

Next, create a folder for components and components files in the root of the app folder.

mkdir components
touch components/ProductScreen.js
touch components/ProductDetailsScreen.js
touch components/ProductAddScreen.js
touch components/ProductEditScreen.js

Open and edit components/ProductScreen.js then add this React codes.

import React, { Component } from 'react';
import { Button, View, Text } from 'react-native';

export default class ProductScreen extends Component {
&nbsp; static navigationOptions = {
&nbsp; &nbsp; title: 'Product List',
&nbsp; };
&nbsp; render() {
&nbsp; &nbsp; return (
&nbsp; &nbsp; &nbsp; <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
&nbsp; &nbsp; &nbsp; &nbsp; <Text>Product List</Text>
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title="Go to Details"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.props.navigation.navigate('ProductDetails')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title="Go to Add Product"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.props.navigation.navigate('AddProduct')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title="Go to Edit Product"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.props.navigation.navigate('EditProduct')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; );
&nbsp; }
}

Open and edit components/ProductDetailsScreen.js then add this React codes.

import React, { Component } from 'react';
import { Button, View, Text } from 'react-native';

export default class ProductDetailsScreen extends Component {
&nbsp; static navigationOptions = {
&nbsp; &nbsp; title: 'Product Details',
&nbsp; };
&nbsp; render() {
&nbsp; &nbsp; return (
&nbsp; &nbsp; &nbsp; <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
&nbsp; &nbsp; &nbsp; &nbsp; <Text>Product Details</Text>
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title="Go to Details... again"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.props.navigation.push('ProductDetails')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title="Go to Home"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.props.navigation.navigate('Product')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title="Go back"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.props.navigation.goBack()}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; );
&nbsp; }
}

Open and edit components/ProductAddScreen.js then add this React codes.

import React, { Component } from 'react';
import { Button, View, Text } from 'react-native';

export default class ProductAddScreen extends Component {
&nbsp; static navigationOptions = {
&nbsp; &nbsp; title: 'Add Product',
&nbsp; };
&nbsp; render() {
&nbsp; &nbsp; return (
&nbsp; &nbsp; &nbsp; <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
&nbsp; &nbsp; &nbsp; &nbsp; <Text>Add Product</Text>
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title="Go to Add Product... again"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.props.navigation.push('AddProduct')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title="Go to Home"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.props.navigation.navigate('Product')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title="Go back"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.props.navigation.goBack()}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; );
&nbsp; }
}

Open and edit components/ProductEditScreen.js then add this React codes.

import React, { Component } from 'react';
import { Button, View, Text } from 'react-native';

export default class ProductEditScreen extends Component {
&nbsp; static navigationOptions = {
&nbsp; &nbsp; title: 'Edit Product',
&nbsp; };
&nbsp; render() {
&nbsp; &nbsp; return (
&nbsp; &nbsp; &nbsp; <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
&nbsp; &nbsp; &nbsp; &nbsp; <Text>Add Product</Text>
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title="Go to Edit Product... again"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.props.navigation.push('EditProduct')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title="Go to Home"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.props.navigation.navigate('Product')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title="Go back"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.props.navigation.goBack()}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; );
&nbsp; }
}

Next, open and edit App.js then add replace all codes with this.

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { createAppContainer, createStackNavigator } from 'react-navigation';
import ProductScreen from './components/ProductScreen';
import ProductDetailsScreen from './components/ProductDetailsScreen';
import ProductAddScreen from './components/ProductAddScreen';
import ProductEditScreen from './components/ProductEditScreen';

const RootStack = createStackNavigator(
&nbsp; {
&nbsp; &nbsp; Product: ProductScreen,
&nbsp; &nbsp; ProductDetails: ProductDetailsScreen,
&nbsp; &nbsp; AddProduct: ProductAddScreen,
&nbsp; &nbsp; EditProduct: ProductEditScreen,
&nbsp; },
&nbsp; {
&nbsp; &nbsp; initialRouteName: 'Product',
&nbsp; &nbsp; navigationOptions: {
&nbsp; &nbsp; &nbsp; headerStyle: {
&nbsp; &nbsp; &nbsp; &nbsp; backgroundColor: '#777777',
&nbsp; &nbsp; &nbsp; },
&nbsp; &nbsp; &nbsp; headerTintColor: '#fff',
&nbsp; &nbsp; &nbsp; headerTitleStyle: {
&nbsp; &nbsp; &nbsp; &nbsp; fontWeight: 'bold',
&nbsp; &nbsp; &nbsp; },
&nbsp; &nbsp; },
&nbsp; },
);

const RootContainer = createAppContainer(RootStack);

export default class App extends React.Component {
&nbsp; render() {
&nbsp; &nbsp; return <RootContainer />;
&nbsp; }
}

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

After Re-run the React Native app on the iOS/Android Device/Simulator you will see this updated views.

3. Install and Configure React Native SQLite Storage

Before creating an offline CRUD application using local data, we have to install the react-native-sqlite-storage and required UI/UX module.

yarn add react-native-sqlite-storage --save
yarn add react-native-elements --save
react-native link

We will use separate Class for accessing SQLite and do some CRUD (create, read, update, delete) operations. For that, create a new Javascript file on the root of the project folder.

touch Database.js

Open and edit Database.js then add this SQLite import with the configuration.

import SQLite from "react-native-sqlite-storage";
SQLite.DEBUG(true);
SQLite.enablePromise(true);

Add constant variable after that.

const database_name = "Reactoffline.db";
const database_version = "1.0";
const database_displayname = "SQLite React Offline Database";
const database_size = 200000;

Give this file a class name.

export default class Database {

}

Inside the class bracket, add a function for Database initialization that creates Database, tables, etc.

initDB() {
&nbsp; let db;
&nbsp; return new Promise((resolve) => {
&nbsp; &nbsp; console.log("Plugin integrity check ...");
&nbsp; &nbsp; SQLite.echoTest()
&nbsp; &nbsp; &nbsp; .then(() => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log("Integrity check passed ...");
&nbsp; &nbsp; &nbsp; &nbsp; console.log("Opening database ...");
&nbsp; &nbsp; &nbsp; &nbsp; SQLite.openDatabase(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; database_name,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; database_version,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; database_displayname,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; database_size
&nbsp; &nbsp; &nbsp; &nbsp; )
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .then(DB => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db = DB;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log("Database OPEN");
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db.executeSql('SELECT 1 FROM Product LIMIT 1').then(() => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log("Database is ready ... executing query ...");
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }).catch((error) =>{
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log("Received error: ", error);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log("Database not yet ready ... populating data");
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; db.transaction((tx) => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tx.executeSql('CREATE TABLE IF NOT EXISTS Product (prodId, prodName, prodDesc, prodImage, prodPrice)');
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }).then(() => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log("Table created successfully");
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }).catch(error => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(error);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resolve(db);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; })
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .catch(error => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(error);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; &nbsp; })
&nbsp; &nbsp; &nbsp; .catch(error => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log("echoTest failed - plugin not functional");
&nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; });
};

Add a function for close Database connection.

closeDatabase(db) {
&nbsp; if (db) {
&nbsp; &nbsp; console.log("Closing DB");
&nbsp; &nbsp; db.close()
&nbsp; &nbsp; &nbsp; .then(status => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log("Database CLOSED");
&nbsp; &nbsp; &nbsp; })
&nbsp; &nbsp; &nbsp; .catch(error => {
&nbsp; &nbsp; &nbsp; &nbsp; this.errorCB(error);
&nbsp; &nbsp; &nbsp; });
&nbsp; } else {
&nbsp; &nbsp; console.log("Database was not OPENED");
&nbsp; }
};

Add a function to get the list of products.

listProduct() {
&nbsp; return new Promise((resolve) => {
&nbsp; &nbsp; const products = [];
&nbsp; &nbsp; this.initDB().then((db) => {
&nbsp; &nbsp; &nbsp; db.transaction((tx) => {
&nbsp; &nbsp; &nbsp; &nbsp; tx.executeSql('SELECT p.prodId, p.prodName, p.prodImage FROM Product p', []).then(([tx,results]) => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log("Query completed");
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var len = results.rows.length;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (let i = 0; i < len; i++) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let row = results.rows.item(i);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(`Prod ID: ${row.prodId}, Prod Name: ${row.prodName}`)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const { prodId, prodName, prodImage } = row;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; products.push({
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prodId,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prodName,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prodImage
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(products);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resolve(products);
&nbsp; &nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; &nbsp; }).then((result) => {
&nbsp; &nbsp; &nbsp; &nbsp; this.closeDatabase(db);
&nbsp; &nbsp; &nbsp; }).catch((err) => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; }).catch((err) => {
&nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; });
&nbsp; }); &nbsp;
}

Add a function to get Product by ID.

productById(id) {
&nbsp; console.log(id);
&nbsp; return new Promise((resolve) => {
&nbsp; &nbsp; this.initDB().then((db) => {
&nbsp; &nbsp; &nbsp; db.transaction((tx) => {
&nbsp; &nbsp; &nbsp; &nbsp; tx.executeSql('SELECT * FROM Product WHERE prodId = ?', [id]).then(([tx,results]) => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(results);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(results.rows.length > 0) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let row = results.rows.item(0);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resolve(row);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; &nbsp; }).then((result) => {
&nbsp; &nbsp; &nbsp; &nbsp; this.closeDatabase(db);
&nbsp; &nbsp; &nbsp; }).catch((err) => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; }).catch((err) => {
&nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; });
&nbsp; }); &nbsp;
}

Add a function to save a new product to the SQLite database.

addProduct(prod) {
&nbsp; return new Promise((resolve) => {
&nbsp; &nbsp; this.initDB().then((db) => {
&nbsp; &nbsp; &nbsp; db.transaction((tx) => {
&nbsp; &nbsp; &nbsp; &nbsp; tx.executeSql('INSERT INTO Product VALUES (?, ?, ?, ?, ?)', [prod.prodId, prod.prodName, prod.prodDesc, prod.prodImage, prod.prodPrice]).then(([tx, results]) => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resolve(results);
&nbsp; &nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; &nbsp; }).then((result) => {
&nbsp; &nbsp; &nbsp; &nbsp; this.closeDatabase(db);
&nbsp; &nbsp; &nbsp; }).catch((err) => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; }).catch((err) => {
&nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; });
&nbsp; }); &nbsp;
}

Add a function to update a product.

updateProduct(id, prod) {
&nbsp; return new Promise((resolve) => {
&nbsp; &nbsp; this.initDB().then((db) => {
&nbsp; &nbsp; &nbsp; db.transaction((tx) => {
&nbsp; &nbsp; &nbsp; &nbsp; tx.executeSql('UPDATE Product SET prodName = ?, prodDesc = ?, prodImage = ?, prodPrice = ? WHERE prodId = ?', [prod.prodName, prod.prodDesc, prod.prodImage, prod.prodPrice, id]).then(([tx, results]) => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resolve(results);
&nbsp; &nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; &nbsp; }).then((result) => {
&nbsp; &nbsp; &nbsp; &nbsp; this.closeDatabase(db);
&nbsp; &nbsp; &nbsp; }).catch((err) => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; }).catch((err) => {
&nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; });
&nbsp; }); &nbsp;
}

Add a function to delete a product.

deleteProduct(id) {
&nbsp; return new Promise((resolve) => {
&nbsp; &nbsp; this.initDB().then((db) => {
&nbsp; &nbsp; &nbsp; db.transaction((tx) => {
&nbsp; &nbsp; &nbsp; &nbsp; tx.executeSql('DELETE FROM Product WHERE prodId = ?', [id]).then(([tx, results]) => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(results);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resolve(results);
&nbsp; &nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; &nbsp; }).then((result) => {
&nbsp; &nbsp; &nbsp; &nbsp; this.closeDatabase(db);
&nbsp; &nbsp; &nbsp; }).catch((err) => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; }).catch((err) => {
&nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; });
&nbsp; }); &nbsp;
}

4. Show List of Product

To show or display the list of product, open and edit components/ProductScreen.js then replace all imports with these imports.

import React, { Component } from 'react';
import { StyleSheet, FlatList, ActivityIndicator, View, Text } from 'react-native';
import { ListItem, Button } from 'react-native-elements';
import Database from '../Database';

Instantiate the Database as a constant variable before the class name.

const db = new Database();

Next, replace navigationOptions with these.

static navigationOptions = ({ navigation }) => {
&nbsp; return {
&nbsp; &nbsp; title: 'Product List',
&nbsp; &nbsp; headerRight: (
&nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; buttonStyle={{ padding: 0, backgroundColor: 'transparent' }}
&nbsp; &nbsp; &nbsp; &nbsp; icon={{ name: 'add-circle', style: { marginRight: 0, fontSize: 28 } }}
&nbsp; &nbsp; &nbsp; &nbsp; onPress={() => {&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; navigation.navigate('AddProduct', {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onNavigateBack: this.handleOnNavigateBack
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; }}
&nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; ),
&nbsp; };
};

Add a constructor function.

constructor() {
&nbsp; super();
&nbsp; this.state = {
&nbsp; &nbsp; isLoading: true,
&nbsp; &nbsp; products: [],
&nbsp; &nbsp; notFound: 'Products not found.\nPlease click (+) button to add it.'
&nbsp; };
}

Add a function to initialize the screen.

componentDidMount() {
&nbsp; this._subscribe = this.props.navigation.addListener('didFocus', () => {
&nbsp; &nbsp; this.getProducts();
&nbsp; });
}

Add a function to get the product list from Database class.

getProducts() {
&nbsp; let products = [];
&nbsp; db.listProduct().then((data) => {
&nbsp; &nbsp; products = data;
&nbsp; &nbsp; this.setState({
&nbsp; &nbsp; &nbsp; products,
&nbsp; &nbsp; &nbsp; isLoading: false,
&nbsp; &nbsp; });
&nbsp; }).catch((err) => {
&nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; this.setState = {
&nbsp; &nbsp; &nbsp; isLoading: false
&nbsp; &nbsp; }
&nbsp; })
}

Add a variable to iterate the listed product in the view.

keyExtractor = (item, index) => index.toString()

Add a function to render the List Item.

renderItem = ({ item }) => (
&nbsp; <ListItem
&nbsp; &nbsp; title={item.prodName}
&nbsp; &nbsp; leftAvatar={{
&nbsp; &nbsp; &nbsp; source: item.prodImage && { uri: item.prodImage },
&nbsp; &nbsp; &nbsp; title: item.prodName[0]
&nbsp; &nbsp; }}
&nbsp; &nbsp; onPress={() => {
&nbsp; &nbsp; &nbsp; this.props.navigation.navigate('ProductDetails', {
&nbsp; &nbsp; &nbsp; &nbsp; prodId: `${item.prodId}`,
&nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; }}
&nbsp; &nbsp; chevron
&nbsp; &nbsp; bottomDivider
&nbsp; />
)

Add a function to render the rest of List view.

render() {
&nbsp; if(this.state.isLoading){
&nbsp; &nbsp; return(
&nbsp; &nbsp; &nbsp; <View style={styles.activity}>
&nbsp; &nbsp; &nbsp; &nbsp; <ActivityIndicator size="large" color="#0000ff"/>
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; )
&nbsp; }
&nbsp; if(this.state.products.length === 0){
&nbsp; &nbsp; return(
&nbsp; &nbsp; &nbsp; <View>
&nbsp; &nbsp; &nbsp; &nbsp; <Text style={styles.message}>{this.state.notFound}</Text>
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; )
&nbsp; }
&nbsp; return (
&nbsp; &nbsp; <FlatList
&nbsp; &nbsp; &nbsp; keyExtractor={this.keyExtractor}
&nbsp; &nbsp; &nbsp; data={this.state.products}
&nbsp; &nbsp; &nbsp; renderItem={this.renderItem}
&nbsp; &nbsp; />
&nbsp; );
}

Finally, add a stylesheet for the whole screen after the class bracket.

const styles = StyleSheet.create({
&nbsp; container: {
&nbsp; &nbsp;flex: 1,
&nbsp; &nbsp;paddingBottom: 22
&nbsp; },
&nbsp; item: {
&nbsp; &nbsp; padding: 10,
&nbsp; &nbsp; fontSize: 18,
&nbsp; &nbsp; height: 44,
&nbsp; },
&nbsp; activity: {
&nbsp; &nbsp; position: 'absolute',
&nbsp; &nbsp; left: 0,
&nbsp; &nbsp; right: 0,
&nbsp; &nbsp; top: 0,
&nbsp; &nbsp; bottom: 0,
&nbsp; &nbsp; alignItems: 'center',
&nbsp; &nbsp; justifyContent: 'center'
&nbsp; },
&nbsp; message: {
&nbsp; &nbsp; padding: 16,
&nbsp; &nbsp; fontSize: 18,
&nbsp; &nbsp; color: 'red'
&nbsp; }
});

5. Show Product Details and Delete Product

From the list of product view, you will see that list item has an action button to show the product details. Next, open and edit components/ProductDetailsScreen.js then replace the imports with these imports.

import React, { Component } from 'react';
import { ScrollView, StyleSheet, Image, ActivityIndicator, View, Text } from 'react-native';
import { Card, Button } from 'react-native-elements';
import Database from '../Database';

Instantiate the Database as a constant variable.

const db = new Database();

Add a function as the constructor.

constructor() {
&nbsp; super();
&nbsp; this.state = {
&nbsp; &nbsp; isLoading: true,
&nbsp; &nbsp; product: {},
&nbsp; &nbsp; id: '',
&nbsp; };
}

Add a function to initialize the screen.

componentDidMount() {
&nbsp; this._subscribe = this.props.navigation.addListener('didFocus', () => {
&nbsp; &nbsp; const { navigation } = this.props;
&nbsp; &nbsp; db.productById(navigation.getParam('prodId')).then((data) => {
&nbsp; &nbsp; &nbsp; console.log(data);
&nbsp; &nbsp; &nbsp; product = data;
&nbsp; &nbsp; &nbsp; this.setState({
&nbsp; &nbsp; &nbsp; &nbsp; product,
&nbsp; &nbsp; &nbsp; &nbsp; isLoading: false,
&nbsp; &nbsp; &nbsp; &nbsp; id: product.prodId
&nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; }).catch((err) => {
&nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; &nbsp; this.setState = {
&nbsp; &nbsp; &nbsp; &nbsp; isLoading: false
&nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; })
&nbsp; });
}

Add a function to delete a product data.

deleteProduct(id) {
&nbsp; const { navigation } = this.props;
&nbsp; this.setState({
&nbsp; &nbsp; isLoading: true
&nbsp; });
&nbsp; db.deleteProduct(id).then((result) => {
&nbsp; &nbsp; console.log(result);
&nbsp; &nbsp; this.props.navigation.goBack();
&nbsp; }).catch((err) => {
&nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; this.setState = {
&nbsp; &nbsp; &nbsp; isLoading: false
&nbsp; &nbsp; }
&nbsp; })
}

Add a function to render the whole Product Details view.

render() {
&nbsp; if(this.state.isLoading){
&nbsp; &nbsp; return(
&nbsp; &nbsp; &nbsp; <View style={styles.activity}>
&nbsp; &nbsp; &nbsp; &nbsp; <ActivityIndicator size="large" color="#0000ff" />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; )
&nbsp; }
&nbsp; return (
&nbsp; &nbsp; <ScrollView>
&nbsp; &nbsp; &nbsp; <Card style={styles.container}>
&nbsp; &nbsp; &nbsp; &nbsp; <View style={styles.subContainer}>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <View>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Image
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; style={{width: 150, height: 150}}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; source={{uri: this.state.product.prodImage}}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <View>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Text style={{fontSize: 16}}>Product ID: {this.state.product.prodId}</Text>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <View>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Text style={{fontSize: 16}}>Product Name: {this.state.product.prodName}</Text>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <View>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Text style={{fontSize: 16}}>Product Desc: {this.state.product.prodDesc}</Text>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <View>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Text style={{fontSize: 16}}>Product Price: {this.state.product.prodPrice}</Text>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; &nbsp; <View style={styles.detailButton}>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; large
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; backgroundColor={'#CCCCCC'}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; leftIcon={{name: 'edit'}}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title='Edit'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.props.navigation.navigate('EditProduct', {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prodId: `${this.state.id}`,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }} />
&nbsp; &nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; &nbsp; <View style={styles.detailButton}>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; large
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; backgroundColor={'#999999'}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; color={'#FFFFFF'}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; leftIcon={{name: 'delete'}}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title='Delete'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.deleteProduct(this.state.id)} />
&nbsp; &nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; </Card>
&nbsp; &nbsp; </ScrollView>
&nbsp; );
}

Finally, add the stylesheet for this screen after the class bracket.

const styles = StyleSheet.create({
&nbsp; container: {
&nbsp; &nbsp; flex: 1,
&nbsp; &nbsp; padding: 20
&nbsp; },
&nbsp; subContainer: {
&nbsp; &nbsp; flex: 1,
&nbsp; &nbsp; paddingBottom: 20,
&nbsp; &nbsp; borderBottomWidth: 2,
&nbsp; &nbsp; borderBottomColor: '#CCCCCC',
&nbsp; },
&nbsp; activity: {
&nbsp; &nbsp; position: 'absolute',
&nbsp; &nbsp; left: 0,
&nbsp; &nbsp; right: 0,
&nbsp; &nbsp; top: 0,
&nbsp; &nbsp; bottom: 0,
&nbsp; &nbsp; alignItems: 'center',
&nbsp; &nbsp; justifyContent: 'center'
&nbsp; },
&nbsp; detailButton: {
&nbsp; &nbsp; marginTop: 10
&nbsp; }
})

6. Add Product

To add or save a new Product, open and edit the components/ProductAddScreen.js then replace all imports with these imports.

import React, { Component } from 'react';
import { StyleSheet, ScrollView, ActivityIndicator, View, TextInput } from 'react-native';
import { Button } from 'react-native-elements';
import Database from '../Database';

Instantiate the Database as a constant variable.

const db = new Database();

Add a constructor inside the class bracket after the navigationOptions.

constructor() {
&nbsp; super();
&nbsp; this.state = {
&nbsp; &nbsp; prodId: '',
&nbsp; &nbsp; prodName: '',
&nbsp; &nbsp; prodDesc: '',
&nbsp; &nbsp; prodImage: '',
&nbsp; &nbsp; prodPrice: '0',
&nbsp; &nbsp; isLoading: false,
&nbsp; };
}

Add a function to update the input text values.

updateTextInput = (text, field) => {
&nbsp; const state = this.state
&nbsp; state[field] = text;
&nbsp; this.setState(state);
}

Add a function to save a product to the SQLite table.

saveProduct() {
&nbsp; this.setState({
&nbsp; &nbsp; isLoading: true,
&nbsp; });
&nbsp; let data = {
&nbsp; &nbsp; prodId: this.state.prodId,
&nbsp; &nbsp; prodName: this.state.prodName,
&nbsp; &nbsp; prodDesc: this.state.prodDesc,
&nbsp; &nbsp; prodImage: this.state.prodImage,
&nbsp; &nbsp; prodPrice: this.state.prodPrice
&nbsp; }
&nbsp; db.addProduct(data).then((result) => {
&nbsp; &nbsp; console.log(result);
&nbsp; &nbsp; this.setState({
&nbsp; &nbsp; &nbsp; isLoading: false,
&nbsp; &nbsp; });
&nbsp; &nbsp; this.props.navigation.state.params.onNavigateBack;
&nbsp; &nbsp; this.props.navigation.goBack();
&nbsp; }).catch((err) => {
&nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; this.setState({
&nbsp; &nbsp; &nbsp; isLoading: false,
&nbsp; &nbsp; });
&nbsp; })
}

Add a function to render the whole add product view.

render() {
&nbsp; if(this.state.isLoading){
&nbsp; &nbsp; return(
&nbsp; &nbsp; &nbsp; <View style={styles.activity}>
&nbsp; &nbsp; &nbsp; &nbsp; <ActivityIndicator size="large" color="#0000ff"/>
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; )
&nbsp; }
&nbsp; return (
&nbsp; &nbsp; <ScrollView style={styles.container}>
&nbsp; &nbsp; &nbsp; <View style={styles.subContainer}>
&nbsp; &nbsp; &nbsp; &nbsp; <TextInput
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder={'Product ID'}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value={this.state.prodId}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChangeText={(text) => this.updateTextInput(text, 'prodId')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; <View style={styles.subContainer}>
&nbsp; &nbsp; &nbsp; &nbsp; <TextInput
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder={'Product Name'}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value={this.state.prodName}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChangeText={(text) => this.updateTextInput(text, 'prodName')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; <View style={styles.subContainer}>
&nbsp; &nbsp; &nbsp; &nbsp; <TextInput
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; multiline={true}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; numberOfLines={4}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder={'Product Description'}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value={this.state.prodDesc}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChangeText={(text) => this.updateTextInput(text, 'prodDesc')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; <View style={styles.subContainer}>
&nbsp; &nbsp; &nbsp; &nbsp; <TextInput
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder={'Product Image'}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value={this.state.prodImage}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChangeText={(text) => this.updateTextInput(text, 'prodImage')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; <View style={styles.subContainer}>
&nbsp; &nbsp; &nbsp; &nbsp; <TextInput
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder={'Product Price'}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value={this.state.prodPrice}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keyboardType='numeric'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChangeText={(text) => this.updateTextInput(text, 'prodPrice')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; <View style={styles.button}>
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; large
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; leftIcon={{name: 'save'}}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title='Save'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.saveProduct()} />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; </ScrollView>
&nbsp; );
}

Finally, add the style for the whole screen.

const styles = StyleSheet.create({
&nbsp; container: {
&nbsp; &nbsp; flex: 1,
&nbsp; &nbsp; padding: 20
&nbsp; },
&nbsp; subContainer: {
&nbsp; &nbsp; flex: 1,
&nbsp; &nbsp; marginBottom: 20,
&nbsp; &nbsp; padding: 5,
&nbsp; &nbsp; borderBottomWidth: 2,
&nbsp; &nbsp; borderBottomColor: '#CCCCCC',
&nbsp; },
&nbsp; activity: {
&nbsp; &nbsp; position: 'absolute',
&nbsp; &nbsp; left: 0,
&nbsp; &nbsp; right: 0,
&nbsp; &nbsp; top: 0,
&nbsp; &nbsp; bottom: 0,
&nbsp; &nbsp; alignItems: 'center',
&nbsp; &nbsp; justifyContent: 'center'
&nbsp; }
})

7. Edit Product

To edit a product, open and edit components/ProductEditScreen.js then replace all imports with these imports.

import React, { Component } from 'react';
import { StyleSheet, ScrollView, ActivityIndicator, View, TextInput } from 'react-native';
import { Button } from 'react-native-elements';
import Database from '../Database';

Instantiate the Database as a constant variable.

const db = new Database();

Add the constructor after the navigationOptions function.

constructor() {
&nbsp; super();
&nbsp; this.state = {
&nbsp; &nbsp; prodId: '',
&nbsp; &nbsp; prodName: '',
&nbsp; &nbsp; prodDesc: '',
&nbsp; &nbsp; prodImage: '',
&nbsp; &nbsp; prodPrice: '0',
&nbsp; &nbsp; isLoading: true,
&nbsp; };
}

Add a function to initialize the screen that will get product data.

componentDidMount() {
&nbsp; const { navigation } = this.props;
&nbsp; db.productById(navigation.getParam('prodId')).then((data) => {
&nbsp; &nbsp; console.log(data);
&nbsp; &nbsp; const product = data;
&nbsp; &nbsp; this.setState({
&nbsp; &nbsp; &nbsp; prodId: product.prodId,
&nbsp; &nbsp; &nbsp; prodName: product.prodName,
&nbsp; &nbsp; &nbsp; prodDesc: product.prodDesc,
&nbsp; &nbsp; &nbsp; prodImage: product.prodImage,
&nbsp; &nbsp; &nbsp; prodPrice: product.prodPrice,
&nbsp; &nbsp; &nbsp; isLoading: false,
&nbsp; &nbsp; });
&nbsp; }).catch((err) => {
&nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; this.setState = {
&nbsp; &nbsp; &nbsp; isLoading: false
&nbsp; &nbsp; }
&nbsp; })
}

Add a function to update the input text value.

updateTextInput = (text, field) => {
&nbsp; const state = this.state
&nbsp; state[field] = text;
&nbsp; this.setState(state);
}

Add a function to update the product data.

updateProduct() {
&nbsp; this.setState({
&nbsp; &nbsp; isLoading: true,
&nbsp; });
&nbsp; const { navigation } = this.props;
&nbsp; let data = {
&nbsp; &nbsp; prodId: this.state.prodId,
&nbsp; &nbsp; prodName: this.state.prodName,
&nbsp; &nbsp; prodDesc: this.state.prodDesc,
&nbsp; &nbsp; prodImage: this.state.prodImage,
&nbsp; &nbsp; prodPrice: this.state.prodPrice
&nbsp; }
&nbsp; db.updateProduct(data.prodId, data).then((result) => {
&nbsp; &nbsp; console.log(result);
&nbsp; &nbsp; this.setState({
&nbsp; &nbsp; &nbsp; isLoading: false,
&nbsp; &nbsp; });
&nbsp; &nbsp; this.props.navigation.state.params.onNavigateBack;
&nbsp; &nbsp; this.props.navigation.goBack();
&nbsp; }).catch((err) => {
&nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; this.setState({
&nbsp; &nbsp; &nbsp; isLoading: false,
&nbsp; &nbsp; });
&nbsp; })
}

Add a function to render the whole Edit Product screen.

render() {
&nbsp; if(this.state.isLoading){
&nbsp; &nbsp; return(
&nbsp; &nbsp; &nbsp; <View style={styles.activity}>
&nbsp; &nbsp; &nbsp; &nbsp; <ActivityIndicator size="large" color="#0000ff"/>
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; )
&nbsp; }
&nbsp; return (
&nbsp; &nbsp; <ScrollView style={styles.container}>
&nbsp; &nbsp; &nbsp; <View style={styles.subContainer}>
&nbsp; &nbsp; &nbsp; &nbsp; <TextInput
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder={'Product ID'}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value={this.state.prodId}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChangeText={(text) => this.updateTextInput(text, 'prodId')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; <View style={styles.subContainer}>
&nbsp; &nbsp; &nbsp; &nbsp; <TextInput
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder={'Product Name'}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value={this.state.prodName}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChangeText={(text) => this.updateTextInput(text, 'prodName')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; <View style={styles.subContainer}>
&nbsp; &nbsp; &nbsp; &nbsp; <TextInput
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; multiline={true}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; numberOfLines={4}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder={'Product Description'}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value={this.state.prodDesc}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChangeText={(text) => this.updateTextInput(text, 'prodDesc')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; <View style={styles.subContainer}>
&nbsp; &nbsp; &nbsp; &nbsp; <TextInput
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder={'Product Image'}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value={this.state.prodImage}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChangeText={(text) => this.updateTextInput(text, 'prodImage')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; <View style={styles.subContainer}>
&nbsp; &nbsp; &nbsp; &nbsp; <TextInput
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder={'Product Price'}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value={this.state.prodPrice}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keyboardType='numeric'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChangeText={(text) => this.updateTextInput(text, 'prodPrice')}
&nbsp; &nbsp; &nbsp; &nbsp; />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; &nbsp; <View style={styles.button}>
&nbsp; &nbsp; &nbsp; &nbsp; <Button
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; large
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; leftIcon={{name: 'save'}}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title='Save'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onPress={() => this.updateProduct()} />
&nbsp; &nbsp; &nbsp; </View>
&nbsp; &nbsp; </ScrollView>
&nbsp; );
}

Finally, add the stylesheet after the class bracket.

const styles = StyleSheet.create({
&nbsp; container: {
&nbsp; &nbsp; flex: 1,
&nbsp; &nbsp; padding: 20
&nbsp; },
&nbsp; subContainer: {
&nbsp; &nbsp; flex: 1,
&nbsp; &nbsp; marginBottom: 20,
&nbsp; &nbsp; padding: 5,
&nbsp; &nbsp; borderBottomWidth: 2,
&nbsp; &nbsp; borderBottomColor: '#CCCCCC',
&nbsp; },
&nbsp; activity: {
&nbsp; &nbsp; position: 'absolute',
&nbsp; &nbsp; left: 0,
&nbsp; &nbsp; right: 0,
&nbsp; &nbsp; top: 0,
&nbsp; &nbsp; bottom: 0,
&nbsp; &nbsp; alignItems: 'center',
&nbsp; &nbsp; justifyContent: 'center'
&nbsp; }
})

8. Run and Test React Native and SQLite Offline Mobile App

As we show you at the first step, run the React Native and SQLite app using this command.

react-native run-android
react-native run-ios

After the new terminal window open, just go to the project folder then run this command.

react-native start

Now, you will see the whole application in the Android/iOS Device.

That it’s, the React Native and SQLite Offline Mobile App. You can get the full source code from our GitHub.

Build Android/iOS Mobile Apps with Capacitor, React.js and Ionic 4

Build Android/iOS Mobile Apps with Capacitor, React.js and Ionic 4

In this artilce, you'll learn how to 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.The Android/iOS mobile apps that we will build is very simple. Just show the list of data that get from the RESTful API using the Axios library. The RESTful 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 RESTful 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 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](https://morioh.com/p/9c65c77b47e0 "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 RESTful API and Display as List

As mention above, we will use Axios to fetch data from RESTful 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.

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 RESTful 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 RESTful 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>&nbsp;</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.