React Native – How To Apply Run Time Android Permission In React Native ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article ( How To Apply Run Time Android Permission In React Native ).

In this article, we will learn how to apply Run Time Android Permission In React Native. Android Permission feature helps a user to know which application is trying to access sensitive data such as files, contacts and SMS, and system-specific features such as camera and internet. This article shows to apply the run time permission with the authentic example.

To understand the Run Time Android Permission In React Native, we cover the below topics as below :

  • What is Android Permission?
  • Why we need permission?
  • How to apply Permission in Android?
  • How to apply run time Permission in React Native?
  • Example to apply the run time permission.

A famous quote about learning is :

” The great aim of education is not knowledge, but action. “

So Let’s begin.


What is Android Permission ?

According to Google’s privacy policy, a user should know which application is trying to access sensitive data such as files, contacts and SMS, and system-specific features such as camera and internet. So they introduced the Android Permission feature.

In Android permission modal, every application which is using sensitive data or some certain system features has to ask the permissions from the user.

The purpose of permission is to protect the privacy of an Android user.


Why We need Permission ?

Android applies the permission modal because some applications were tracking the user’s location in the background and accessing the private data like contacts, call history and messages without informing the user which is the violation of googles privacy policy.

So solving this sensitive issue application has to ask for permission to access those sensitive data.


How to Apply Permission in Android ?

Now we get an idea about the Android permission, let’s see how to apply the permission in Android.

To apply permission in Android, we have to follow two steps:

  1. We have to add those permissions requests in project -> app -> src -> AndroidManifest.xml file.

For Example, if we want to ask for the device location Permission, we have to add the following permission request in AndroidManifest.xml :

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

After adding the permission in AndroidManifest file, this permission will be automatically asked by the play store when they install the app and this permission will be granted to the applications.

On devices before SDK version 23, the permissions are automatically granted if we add those permissions in our AndroidManifest.xml file, but after SDK version 23 we have to ask runtime permission as well.

2. After Google’s new permission modal, they have introduced the run time permission mechanism in Android version 23. According to that, we have to include all the permissions in AndroidManifest.xml and also have to apply some dangerous permissions in run time.

According to the official docs, dangerous permissions require a dialog prompt.

So whenever we are working with this dangerous permissions, we need to check whether the permission is granted by the user, and that can be done with the help of PermissionsAndroid in React Native.

For example, If we need INTERNET permission and CAMERA permission then we have to add both the permission in AndroidManifest.xml file but have to ask only for the CAMERA permission in run time because CAMERA permission comes under the dangerous permission not INTERNET permission.

Run Time Permissions that requires Confirmation from the User. Here is the list of dangerous permissions.

READ_CALENDARandroid.permission.READ_CALENDAR
WRITE_CALENDARandroid.permission.WRITE_CALENDAR
CAMERAandroid.permission.CAMERA
READ_CONTACTSandroid.permission.READ_CONTACTS
WRITE_CONTACTSandroid.permission.WRITE_CONTACTS
GET_ACCOUNTSandroid.permission.GET_ACCOUNTS
ACCESS_FINE_LOCATIONandroid.permission.ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATIONandroid.permission.ACCESS_COARSE_LOCATION
RECORD_AUDIOandroid.permission.RECORD_AUDIO
READ_PHONE_STATEandroid.permission.READ_PHONE_STATE
CALL_PHONEandroid.permission.CALL_PHONE
READ_CALL_LOGandroid.permission.READ_CALL_LOG
WRITE_CALL_LOGandroid.permission.WRITE_CALL_LOG
ADD_VOICEMAILcom.android.voicemail
USE_SIPandroid.permission.USE_SIP
PROCESS_OUTGOING_CALLSandroid.permission.PROCESS_OUTGOING_CALLS
BODY_SENSORSandroid.permission.BODY_SENSORS
SEND_SMSandroid.permission.SEND_SMS
RECEIVE_SMSandroid.permission.RECEIVE_SMS
READ_SMSandroid.permission.READ_SMS
RECEIVE_WAP_PUSHandroid.permission.RECEIVE_WAP_PUSH
RECEIVE_MMSandroid.permission.RECEIVE_MMS
READ_EXTERNAL_STORAGEandroid.permission.READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGEandroid.permission.WRITE_EXTERNAL_STORAGE
Run Time Permissions


How to apply Run Time Android Permission using React Native PermissionsAndroid ?

In React Native, PermissionsAndroid component provides access to Android M’s (Over API level 23) new permissions model. We always need to check the permission before using native APIs which comes under dangerous permissions.

Above mentioned all the dangerous permissions comes under PermissionsAndroid.PERMISSIONS as constants.

We can check the permission granted or not using PermissionsAndroid.RESULTS.GRANTED.

To apply the permission to use

PermissionsAndroid.request(permission name,{Permission dialog heading, body})

Result Strings for Requesting Permissions

As constants under PermissionsAndroid.RESULTS:

ResponseResult
GRANTEDPermission granted successfully by the user
DENIEDPermission denied by the user
NEVER_ASK_AGAINPermission denied by the user with never ask again.
Result Strings for Requesting Permissions

Now we get an idea about Android permissions and components. Let’s move towards the Example which can help us apply permission in our application.


Example to Apply the Run Time Permission

In this example, we will apply the device location permission, which needs run time permission. We are making a button on the centre of the screen and on a click of button we will apply the run time permission for device location known as ACCESS_FINE_LOCATION. So let’s get started.


Example Project Setup

To demonstration of apply the Run Time Permission, we have to follow the below steps:

  • Create a new React Native project
  • Adding device location permission in AndroidManifest.xml


1. Create a new React Native project

Assuming that we have node installed, we can use npm to install the react-native-cli command line utility. Open the terminal and go to the workspace and run the following commands to create a new React Native project.

npx react-native init ProjectName

This will make a project structure with an index file named App.js in our project directory.


2. Adding device location permission in AndroidManifest.xml

If we are using any features in our app that needs permission, we need to add it in AndroidManifest.xml. For this example, we are adding device location permission in AndroidManifest.xml.

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Android Permission

Now jump into the project using

cd ProjectName


Example Code to Apply for the Run Time Permission

Open App.js in any code editor and replace the code with the following code.

App.js

import React, {Component} from 'react';

import {
  Platform,
  StyleSheet,
  View,
  PermissionsAndroid,
  Text,
  Alert,
} from 'react-native';

export async function request_location_runtime_permission() {
  try {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
      {
        title: 'ReactNativeCode Location Permission',
        message: 'ReactNativeCode App needs access to your location ',
      },
    );
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      Alert.alert('Location Permission Granted.');
    } else {
      Alert.alert('Location Permission Not Granted');
    }
  } catch (err) {
    console.warn(err);
  }
}

export default class App extends Component {
  async componentDidMount() {
    await request_location_runtime_permission();
  }

  render() {
    return (
      <View style={styles.MainContainer}>
        <Text>React Native Runtime Permission Request</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  MainContainer: {
    flex: 1,
    paddingTop: Platform.OS === 'ios' ? 20 : 0,
    justifyContent: 'center',
    margin: 20,
  },
});

Here PermissionsAndroid.request has two arguments:

  1. PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION to generate a dialog to ask for Device Location Permission.
  2. A JSON {‘title’:”,’message’:”}, which will help us to communicate or to show the dialog about the permission if the user denied the permission. They will generate it like this.
Android Permission Dialog Box


To Run the React Native Example Code

Open the terminal again, and jump into our project using

cd ProjectName

To run the project on an Android Virtual Device or on real debugging device

npx react-native run-android

or on the iOS Simulator by running (macOS only)

npx react-native run-ios (macOS only).

The output of example code is as below:

Android Permission Grant Example Output Screenshot

That’s all about in this article.


Conclusion

In this article, we understood how to apply Run Time Android Permission in React Native. This article showed the example code to apply the RunTime Android Permission in React Native.

Thanks for reading! I hope you enjoyed and learned about RunTime Android Permission Concepts in React Native. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow official website and tutorials of React Native as below links :

React Native Official Website

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING!!???

React Native – The Most Popular Best Ways To Make REST API Calls In React Native

Hello Readers, CoolMonkTechie heartily welcomes you in this article (The most popular best ways to make REST API Calls in React Native ).

In this article, we will learn about different best ways to make REST API Calls in React Native. Many mobile apps need to load resources from a remote URL. We may want to make a POST request to a REST API, or we may need to fetch a chunk of static content from another server.

Applications on the web and mobile devices often cannot store all the information that they need. Therefore, they have to reach out to the web to update data, retrieve data, or request a service from a third-party. The transaction that takes place between two devices (client and server) is called an API call. An API (application programming interface) typically will use the REST design paradigm to manage all how it can be accessed (called).

This article shows the fetch function and the axios library. Both methods achieve the same task, making an HTTP call, but they go about it in slightly different ways.

A famous quote about learning is :

” The expert in anything was once a beginner. “

So Let’s begin.

Using Fetch

React Native provides the Fetch API for our networking needs. Fetch will seem familiar if we have used XMLHttpRequest or other networking APIs before. The Fetch API is a built-in Javascript function. We can use fetch by providing the URL for the location of our content. This will send a GET request to that URL.

Making Requests

In order to fetch content from an arbitrary URL, we can pass the URL to fetch:

fetch('https://mywebsite.com/mydata.json');

Fetch also takes an optional second argument that allows us to customize the HTTP request. We may want to specify additional headers, or make a POST request:

fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    firstParam: 'yourValue',
    secondParam: 'yourOtherValue'
  })
});

We can follow at the Fetch Request docs for a full list of properties.

Handling The Response

The above examples show how we can make a request. Most times, we will want to do something with the response.

Networking is an inherently asynchronous operation. Fetch methods will return a Promise that makes it straightforward to write code that works asynchronously:

const getMoviesFromApi = () => {
  return fetch('https://reactnative.dev/movies.json')
    .then((response) => response.json())
    .then((json) => {
      return json.movies;
    })
    .catch((error) => {
      console.error(error);
    });
};

We can read through the above code like;

  1. Fetch the data at the URL 'https://reactnative.dev/movies.json'
  2. Then, transform the response into JSON
  3. Then, return the movies property on the JSON object
  4. If there is an error, log the error to the console.

We can also use the async / await syntax in a React Native app:

const getMoviesFromApiAsync = async () => {
  try {
    let response = await fetch(
      'https://reactnative.dev/movies.json'
    );
    let json = await response.json();
    return json.movies;
  } catch (error) {
    console.error(error);
  }
};

We need to catch any errors that may be thrown by fetch, otherwise they will be dropped silently.

Fetch Example

import React, { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';

export default App = () => {
  const [isLoading, setLoading] = useState(true);
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch('https://reactnative.dev/movies.json')
      .then((response) => response.json())
      .then((json) => setData(json.movies))
      .catch((error) => console.error(error))
      .finally(() => setLoading(false));
  }, []);

  return (
    <View style={{ flex: 1, padding: 24 }}>
      {isLoading ? <ActivityIndicator/> : (
        <FlatList
          data={data}
          keyExtractor={({ id }, index) => id}
          renderItem={({ item }) => (
            <Text>{item.title}, {item.releaseYear}</Text>
          )}
        />
      )}
    </View>
  );
};

By default, iOS will block any request that’s not encrypted using SSL. If we need to fetch from a cleartext URL (one that begins with http), then App Transport Security exception will first need to add.

It is more secure to add exceptions only for those domains, If we know ahead of time to need to access the domains; if we do not know the domains until runtime, ATS can completely disable.

This is a simple way to send HTTP requests as soon as possible. However, another popular method for sending HTTP requests is with third-party libraries.

Using XMLHttpRequest API

The XMLHttpRequest API is built into React Native. This means that we can use third-party libraries such as frisbee or axios that depend on it, or we can use the XMLHttpRequest API directly if we prefer.

var request = new XMLHttpRequest();
request.onreadystatechange = (e) => {
  if (request.readyState !== 4) {
    return;
  }

  if (request.status === 200) {
    console.log('success', request.responseText);
  } else {
    console.warn('error');
  }
};

request.open('GET', 'https://mywebsite.com/endpoint/');
request.send();

The security model for XMLHttpRequest differs from on web, as there is no concept of CORS in native apps.

Using WebSocket Protocal

React Native also supports WebSockets , a protocol which provides full-duplex communication channels over a single TCP connection.

var ws = new WebSocket('ws://host.com/path');

ws.onopen = () => {
  // connection opened
  ws.send('something'); // send a message
};

ws.onmessage = (e) => {
  // a message was received
  console.log(e.data);
};

ws.onerror = (e) => {
  // an error occurred
  console.log(e.message);
};

ws.onclose = (e) => {
  // connection closed
  console.log(e.code, e.reason);
};

Using Axios Library

The Axios is a Javascript library used to make HTTP requests, and it supports the Promise API that is native to JS ES6. The Axios library has grown in popularity alongside the increase in apps that exchange information using JSON. Three things that make the Axios library so useful are the ability to;

  • Intercept requests and responses
  • Transform request and response data
  • Automatically transform data for JSON

Axios Library Example

import Axios from 'axios'

Axios({
  url: '/data',
  method: 'get',
  baseURL: 'https://example.com',
  transformRequest: [function (data, headers) {
    // Do whatever you want to transform the data
 
    return data;
  }],
  transformResponse: [function (data) {
    // Do whatever you want to transform the data
 
    return data;
  }],
  headers: {'X-Requested-With': 'XMLHttpRequest'},
  data: {
    name: 'Some Name'
  },
})

In the above example, we have passed a configuration object that calls an example URL with a GET request. We’ll notice that some parameter names are common between fetch and Axios.

Next, let’s look at a smaller GET request.

axios.get('https://example.com/data')
  .then(function (response) {
    return response.names;
  })
  .catch(function (error) {
    console.log(error);
  })

We are calling the same URL as we did with the fetch API, but we don’t have to manually transform the response object into JSON. Axios has more features that can be useful with bigger applications.

That’s all about in this article.

Conclusion

In this article, we understood about different best ways to make REST API Calls in React Native. This article showed the fetch and axios library usage with code snippets in React Native .

Thanks for reading! I hope you enjoyed and learned about REST API Calls concepts in React Native. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow official website and tutorials of React Native as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING!!???

React Native – How To Use Redux With React Hooks In React Native Application ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will learn how to use Redux with React Hooks by building a real React Native Application. Redux is a popular React and React Native state management library, meant to be used in complex React and React Native apps where sharing state between multi-level components can get extremely difficult to manage. React Hooks provide us  the ability to use functional components in React or React Native apps. Their ability to provide support to manage a component’s state and handle side-effects offers an alternative to class components.

In this article, let us look at some hooks provided by the react-redux library that provides a way to avoid writing boilerplate code when using the connect() High Order Component.

To understand the use of Redux with React Hooks in React Native application, We will cover the below steps as below :

  1. Configure a New React Native Application
  2. Create Mock Screens
  3. Set Up a Stack Navigator
  4. Create an Overlay Modal With Transparent Background
  5. Navigate to the Modal Screen
  6. Add a Custom Modal With a Transparent Background
  7. Adding a Text Input in the Custom Modal Screen
  8. Add a Custom Header to the List Screen
  9. Change the StatusBar Appearance
  10. Add a List view
  11. Creating a Root Reducer
  12. Configuring a Store
  13. Implement the useSelector Hook
  14. Adding Items to the List by Dispatching an Action Creator
  15. Adding FlatList to Display the Items in the List
  16. Updating the Header
  17. Removing an Item
  18. The final code of the demo application
  19. The final output of the demo application

A famous quote about learning is :

” The purpose of learning is growth, and our minds, unlike our bodies, can continue growing as we continue to live. “

So Let’s begin.


Step 1 – Configure a New React Native Application

To configure a new React Native app, we are going to use expo-cli with a blank template to generate a new app.

expo init projectname

Firstly, we have generated the project, Then we navigate inside the directory and install the following dependencies.

yarn add redux react-redux @react-navigation/native @react-navigation/stack

We are going to use Stack Navigator from the react-navigation library for two different screens in this demo app. For expo-cli, we run the following command to install required dependencies for the navigator to work.

expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view


Step 2 – Create Mock Screens

In this section, let us create two screens that the app is going to use to display a list of items and allow the user to add to each item. We create a new directory called src/screens and then create two new ListScreen.js and ModalScreen.js files.

Each of these screen files is going to have some random data to display until the stack navigator is set up.

Here is the code snippet for ListScreen.js :

import React from "react";import { StyleSheet, Text, View } from "react-native";function ListScreen() {return (<View style={styles.container}><Text>List Screen</Text></View>);}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: "#fff",alignItems: "center",justifyContent: "center",},});export default ListScreen;

Here is the code snippet for ModalScreen.js :

import React from "react";import { StyleSheet, Text, View } from "react-native";function ModalScreen() {return (<View style={styles.container}><Text>Modal Screen</Text></View>);}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: "#fff",alignItems: "center",justifyContent: "center",},});export default ModalScreen;


Step 3 – Set Up a Stack Navigator

A Stack Navigator allows the app to transit between different or multiple screens and manages the navigation history. We create a new file called AppNavigator.js inside the src/navigation directory. This file is going to contain all the configurations required to set up a Stack Navigator.

With the recent release of react-navigation version 5, the way to configure a stack navigator has changed. The major highlight of these new changes is the component-based configuration. Navigation patterns are now more component-based, common use cases can now be handled with pre-defined Hooks, the new architecture allowing us to configure and update a screen from within the component itself.

import * as React from "react";import { NavigationContainer } from "@react-navigation/native";import { createStackNavigator } from "@react-navigation/stack";import ListScreen from "../screens/ListScreen";import ModalScreen from "../screens/ModalScreen";

The NavigationContainer is a component provided by the react-navigation library that manages the navigation tree. It contains the navigation state and wraps all the navigator’s structure.

The createStackNavigator is a function that implements a stack navigation pattern. This function returns two React components: Screen and Navigator, that are going to allow us to configure each component screen.

const Stack = createStackNavigator();function MainStackNavigator() {return (<NavigationContainer><Stack.Navigator><Stack.Screen name="List" component={ListScreen} /><Stack.Screen name="Modal" component={ModalScreen} /></Stack.Navigator></NavigationContainer>);}export default MainStackNavigator;

Open the App.js file and import the MainStackNavigator in the root of the app as shown below:

import React from "react";import MainStackNavigator from "./src/navigation/AppNavigator";export default function App() {return <MainStackNavigator />;}

Now, we go the terminal window and execute the command expo start. In the simulator or the real device we are running the Expo client, we are going to notice similar results as shown below:

The first screen in the Stack Navigator is ListScreen, which is shown as above.


Step 4 – Create an Overlay Modal With Transparent Background

The modal can be easily configured with a stack navigator with an overlay of transparent background on the screen as they display it. Since the ListScreen is going to be the first screen and display a list of items, the ModalScreen is going to be a dialog. This dialog appears by clicking a button from the ListScreen in the current application and adds a transparent layer on the screen behind it when opened. The previous screen will be visible underneath this dialog.

This can be done by configuring screenOptions on a Stack Navigator. The react-navigation library provides a way to enable the overlay with a property called cardOverlayEnabled.

Modify AppNavigator.js file as following :

function MainStackNavigator() {return (<NavigationContainer><Stack.Navigatormode="modal"headerMode="none"screenOptions={{cardStyle: { backgroundColor: "transparent" },cardOverlayEnabled: true,cardStyleInterpolator: ({ current: { progress } }) => ({cardStyle: {opacity: progress.interpolate({inputRange: [0, 0.5, 0.9, 1],outputRange: [0, 0.25, 0.7, 1],}),},overlayStyle: {opacity: progress.interpolate({inputRange: [0, 1],outputRange: [0, 0.5],extrapolate: "clamp",}),},}),}}><Stack.Screen name="List" component={ListScreen} /><Stack.Screen name="Modal" component={ModalScreen} /></Stack.Navigator></NavigationContainer>);}

We have to configure the styles of both the screens and add a way for the modal dialog to open from the ListScreen.


Step 5 – Navigate to the Modal Screen

To navigate to the modal screen, let’s add a floating action button with an icon to the ListScreen.js screen component.

This button is going to be touchable and on a single touch is going to navigate to the ModalScreen. The navigation is going to be handled by the navigation prop that can be passed as an argument to the functional component ListScreen. This is only possible because the ListScreen is part of the Stack navigator.

Any screen in a React Native app that utilizes a react-navigation library is a route or a part of a navigation pattern that has access to navigation prop.

Modify the ListScreen.js file as below:

import React from "react";import {StyleSheet,StatusBar,Text,View,TouchableOpacity,} from "react-native";import { Ionicons } from "@expo/vector-icons";function ListScreen({ navigation }) {return (<View style={styles.container}><View style={styles.fabContainer}><TouchableOpacityonPress={() => navigation.navigate("Modal")}style={styles.fabButton}><Ionicons name="ios-add" color="#fff" size={70} /></TouchableOpacity></View></View>);}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: "blue",},fabContainer: {justifyContent: "flex-end",flexDirection: "row",position: "absolute",right: 10,bottom: 20,},fabButton: {backgroundColor: "blue",borderRadius: 35,width: 70,height: 70,alignItems: "center",justifyContent: "center",},});export default ListScreen;

We go back to the simulator device, and we are going to notice the changes. The first thing to notice is the action button floating at the bottom right corner.

On pressing this button, a full-screen modal will open.


Step 6 – Add a Custom Modal With a Transparent Background

In this section, let’s change the behavior of how the modal appears on the ListScreen right now and how we want it to be. As an overlay, we also want it to take the only 1/3rd of the current screen.

This modal is going to have an input field in the future to let the user add items to the list. However, for now, it is going to display a text and a close button.

The close button is going to dismiss the modal when the user wants to go back to the List screen without taking any other action. The close button is going to be placed using position: absolute property and is going to use navigation.goBack() pre-defined method to go back to the List screen.

Here is the complete code for the modal screen at this point. Open ModalScreen.js and modify it.

import React from "react";import { StyleSheet, TouchableOpacity, Text, View } from "react-native";import { Ionicons } from "@expo/vector-icons";function ModalScreen({ navigation }) {return (<View style={styles.container}><View style={styles.innerContainer}><View style={styles.closeButtonContainer}><TouchableOpacitystyle={styles.closeButton}onPress={() => navigation.goBack()}><Ionicons name="ios-close" color="#101010" size={40} /></TouchableOpacity></View><View style={styles.modalContainer}><Text style={{ color: "#444", fontSize: 20 }}>What do you want to do?</Text></View></View></View>);}const styles = StyleSheet.create({container: {flex: 1,},innerContainer: {borderTopLeftRadius: 10,borderTopRightRadius: 10,justifyContent: "flex-end",flexDirection: "row",height: "30%",width: "100%",position: "absolute",bottom: 0,right: 0,backgroundColor: "#fff",},closeButtonContainer: {position: "absolute",alignItems: "flex-end",right: 10,},closeButton: {backgroundColor: "#d3d3d3",borderRadius: 20,width: 40,height: 40,top: 10,alignItems: "center",justifyContent: "center",},modalContainer: {justifyContent: "center",alignItems: "center",position: "absolute",margin: 60,top: 10,left: 50,},});export default ModalScreen;

Here is the output you are going to get in the device after this step:


Step 7 – Adding a Text Input in the Custom Modal Screen

In this section, let’s add a text input component from the react-native core. This is going to allow the user to enter the name of the item they want to add to the list. For now, since we haven’t configured the Redux to manage the app state, let us use the hook useState to manage the component state locally.

Open ModalScreen.js and import TextInput from react-native core.

import {StyleSheet,TouchableOpacity,Text,View,TextInput,} from "react-native";

Next, inside the View that has the style of modalContainer add the following TextInput component as well as a touchable submit button. This touchable button is going to navigate back to the list screen when the user has entered a value in the input field.

<View style={styles.modalContainer}><Text style={{ color: "#444", fontSize: 20 }}>What do you want to do?</Text><TextInputstyle={{height: 50,width: 200,padding: 5,borderColor: "gray",borderBottomWidth: 1,}}numberOfLines={1}onChangeText={(value) => setValue(value)}value={value}clearButtonMode="while-editing"/><TouchableOpacitystyle={{marginTop: 10,backgroundColor: "blue",width: 50,height: 50,\alignItems: "center",justifyContent: "center",borderRadius: 5,}}onPress={() => navigation.navigate("List")}><Ionicons name="ios-arrow-dropright-circle" size={40} color="#fff" /></TouchableOpacity></View>;


Step 8 – Add a Custom Header to the List Screen

Create a new file called Header.js inside the directory src/components. This functional component is going to display the header title in the List screen.

Add the following code snippet to the file. We have just created:

import React from "react";import { View, Text, StyleSheet } from "react-native";function Header(props) {const { title } = props;return (<View style={styles.container}><Text style={styles.text}>{title}</Text></View>);}const styles = StyleSheet.create({container: {alignItems: "center",justifyContent: "center",backgroundColor: "blue",height: 125,paddingTop: 20,},text: {color: "#fff",fontSize: 28,fontWeight: "500",},});export default Header;

Next, we go to the ListScreen.js and import this functional component below the other statements.

// after other import statementsimport Header from '../components/Header'

Then add the component to render before the floating button.

function ListScreen({ navigation }) {return (<View style={styles.container}><Header title={"List"} />{/* rest of the code remains same */}</View>);}


Step 9 – Change the StatusBar Appearance

To change the StatusBar appearance, let us import it from the react-native core API.

import {StyleSheet,StatusBar,Text,View,TouchableOpacity,} from "react-native";

Next, using React Fragment short hand with angle brackets, modify the return statement of ListScreen component as below:

function ListScreen({ navigation }) {return (<><StatusBar barStyle="light-content" /><View style={styles.container}><Header title={"List"} /><View style={styles.fabContainer}><TouchableOpacityonPress={() => navigation.navigate("Modal")}style={styles.fabButton}><Ionicons name="ios-add" color="#fff" size={70} /></TouchableOpacity></View></View></>);}

We will now notice that the Status bar has a white appearance.


Step 10 – Add a List view

In this section, let’s implement the main view that is going to display a list of items. In ListScreen.js, add the following functional component called ListView.

function ListView() {return (<Viewstyle={{backgroundColor: "white",flex: 1,borderTopLeftRadius: 20,borderTopRightRadius: 20,paddingHorizontal: 20,paddingVertical: 20,}}><Text>Here goes list items</Text></View>);}

Then, modify the ListScreen to display it below the Header.

<View style={styles.container}><Header title={"List"} /><ListView />{/* rest of the code remains same */}</View>;

Go to the device, we are running the app, and we are going to notice a major difference in its appearance.


Step 11 – Creating a Root Reducer

In this section, we create a new directory called src/redux/ and inside it, a new file called reducer.js. This file is going to have the definition of action types, action creators and the only reducer we are going to create in this app. This reducer is going to be called rootReducer.

Redux is used to manage the state of the whole application. Therefore, it represents this state by one JavaScript object. Think of this object as read-only (immutable), since we cannot change this state or the object because they represent it in the form of a tree. It requires an action to do so.

Actions are similar to events in Redux. And, they can be triggered in the button press, timers or network requests.

Start by defining an action type as below.

export const ADD_ITEM = 'ADD_ITEM'

Then we define the action creator called addItem that is going to take an item from the user’s input and add it to the list. This is the action creator function that we are going to trigger later.

export const addItem = (item) => ({type: ADD_ITEM,payload: item,});

Define an initial state which is going to have an empty array called itemList. Whenever an action is triggered, the state of the application changes. The handling of the application’s state is done by the reducers.

This initial state is going to be passed as a parameter to the rootReducer. Calling the create action is going to invoke the logic defined for the same action type in the reducer.

Using a reducer, we either want to initiate the current app state or update it, without modifying the whole state on each action trigger. The spread operator returned in the action type ADD_ITEM indicates that.

To update the state, in our case, to add an item object to the itemList array, let us use the contact() that is going to return a new array whenever an item is added to the list. This also satisfies the redux philosophy of not mutating the state directly.

const initialState = {itemList: [],};const rootReducer = (state = initialState, action) => {switch (action.type) {case ADD_ITEM:return {...state,itemList: state.itemList.concat({id: Math.random(),name: action.payload,}),};default:return state;}};export default rootReducer;


Step 12 – Configuring a Store

In this section, we create a new file src/redux/store.js. A store is an object that brings the actions and reducers together. This file is going to implement that.

The store provides and holds the state at the application level instead of individual components. Add the following code snippet to it:

import { createStore } from "redux";import rootReducer from "./reducer";const store = createStore(rootReducer);export default store;

Now, we connect this store to the app, we open App.js file and import the store from this file as well as the High Order Component Provider from react-redux npm package. This HOC helps us to pass the store down to the rest of the components of the current app.

import React from "react";import { Provider as StateProvider } from "react-redux";import store from "./src/redux/store";import MainStackNavigator from "./src/navigation/AppNavigator";export default function App() {return (<StateProvider store={store}><MainStackNavigator /></StateProvider>);}


Step 13 – Implement the useSelector Hook

To access state when managing it with Redux, the useSelector hook is provided in the library. It is similar to mapStateToProps argument that is passed inside the connect(). It allows us to extract data from the Redux store state using a selector function.

The major difference between the hook and the argument (the older way) is that the hook may return any value as a result, not just an object.

Inside ListScreen.js add the following import statement.

import { useSelector } from 'react-redux'

Then, we fetch the listItems array using the hook useSelector inside the ListView component. Also, modify its return statement by displaying a message if the list is empty or not.

function ListView() {const listItems = useSelector((state) => state.itemList);return (<Viewstyle={{backgroundColor: "white",flex: 1,borderTopLeftRadius: 20,borderTopRightRadius: 20,paddingHorizontal: 20,paddingVertical: 20,}}>{listItems.length !== 0 ? (<Text>Contains List items</Text>) : (<Text style={{ fontSize: 30 }}>You list is empty :'(</Text>)}</View>);}


Step 14 – Adding Items to the List by Dispatching an Action Creator

The useDispatch() hook completely refers to the dispatch function from the Redux store. This hook is used only when there is a need to dispatch an action. In the ModalScreen.js to add an item based on the value of TextInput, the state has to be updated. This can be done by triggering the action creator method called addItem defined when creating actions inside redux/reducer.js file.

Start by importing the following statements:

import { useDispatch } from 'react-redux'import { addItem } from '../redux/reducer'

Next, inside the ModalScreen component, we create a helper method called onSaveNote which when triggered on submission of the text input, is going to trigger the action creator as well as take the user back to the List screen.

function ModalScreen({ navigation }) {const [value, setValue] = useState("");const dispatch = useDispatch();const onSaveNote = (value) => {dispatch(addItem(value));navigation.navigate("List");};/* rest of the code remains same */}

Lastly, add this helper method as the value of onPress on the submission button.

<TouchableOpacitystyle={{marginTop: 10,backgroundColor: "blue",width: 50,height: 50,alignItems: "center",justifyContent: "center",borderRadius: 5,}}onPress={() => onSaveNote(value)}><Ionicons name="ios-arrow-dropright-circle" size={40} color="#fff" /></TouchableOpacity>;


Step 15 – Adding FlatList to Display the Items in the List

To display a list of items on List screen, we open the file ListScreen.js and import the FlatList from react-native.

import {StyleSheet,StatusBar,Text,View,TouchableOpacity,FlatList,} from "react-native";

Then, modify the ListView render function as below:

{listItems.length !== 0 ? (<FlatListdata={listItems}keyExtractor={(item) => item.id.toString()}renderItem={({ item }) => (<View style={styles.listItemContainer}><View style={styles.listItemMetaContainer}><Text style={styles.itemTitle} numberOfLines={1}>{item.name}</Text></View></View>)}/>) : (<Text style={{ fontSize: 30 }}>You list is empty :'(</Text>);}


Step 16 – Updating the Header

In this section, using the current app’s state, let us display the number of items in the list to be shown in the header as well. This can be done by using useSelector hook from react-redux.

Modify the file components/Header.js as the following:

import React from "react";import { View, Text, StyleSheet } from "react-native";import { useSelector } from "react-redux";function Header(props) {const { title } = props;const listItems = useSelector((state) => state.itemList);return (<View style={styles.container}><Text style={styles.title}>{title}</Text><Text style={styles.subTitle}>Left: {listItems.length}</Text></View>);}const styles = StyleSheet.create({container: {alignItems: "center",justifyContent: "center",backgroundColor: "blue",height: 125,paddingTop: 20,},title: {color: "#fff",fontSize: 28,fontWeight: "500",},subTitle: {paddingTop: 5,fontSize: 18,color: "#fff",},});export default Header;

Here is the updated header bar when there is one item on the list.


Step 17 – Removing an Item

Since we have gone through the process of understanding how redux hooks work with React Native apps, we try adding a remove item button that is going to delete an item from the list as shown below.

Here is the updated redux/reducer file that has action type REMOVE_ITEM.

export const ADD_ITEM = "ADD_ITEM";export const REMOVE_ITEM = "REMOVE_ITEM";export const addItem = (item) => ({type: ADD_ITEM,payload: item,});export const removeItem = (id) => ({type: REMOVE_ITEM,payload: id,});const initialState = {itemList: [],};const rootReducer = (state = initialState, action) => {switch (action.type) {case ADD_ITEM:return {...state,itemList: state.itemList.concat({id: Math.random(),name: action.payload,}),};case REMOVE_ITEM:return {...state,itemList: state.itemList.filter((item) => item.id !== action.payload),};default:return state;}};export default rootReducer;

Also, here is the updated ListScreen.js where we add the button to remove items with corresponding styles.

To trigger an action, we will have to make use of useDispatch() hook.


Step 18 – The final code of the demo application

Here is the final source code of the demo app:


1. src/redux/reducer.js

export const ADD_ITEM = "ADD_ITEM";export const REMOVE_ITEM = "REMOVE_ITEM";export const addItem = (item) => ({type: ADD_ITEM,payload: item,});export const removeItem = (id) => ({type: REMOVE_ITEM,payload: id,});const initialState = {itemList: [],};const rootReducer = (state = initialState, action) => {switch (action.type) {case ADD_ITEM:return {...state,itemList: state.itemList.concat({id: Math.random(),name: action.payload,}),};case REMOVE_ITEM:return {...state,itemList: state.itemList.filter((item) => item.id !== action.payload),};default:return state;}};export default rootReducer;


2. src/redux/store.js

import { createStore } from "redux";import rootReducer from "./reducer";const store = createStore(rootReducer);export default store;


3. src/components/Header.js

import React from "react";import { View, Text, StyleSheet } from "react-native";import { useSelector } from "react-redux";function Header(props) {const { title } = props;const listItems = useSelector((state) => state.itemList);return (<View style={styles.container}><Text style={styles.title}>{title}</Text><Text style={styles.subTitle}>Left: {listItems.length}</Text></View>);}const styles = StyleSheet.create({container: {alignItems: "center",justifyContent: "center",backgroundColor: "blue",height: 125,paddingTop: 20,},title: {color: "#fff",fontSize: 28,fontWeight: "500",},subTitle: {paddingTop: 5,fontSize: 18,color: "#fff",},});export default Header;


4. src/navigation/AppNavigator.js

import * as React from "react";import { NavigationContainer } from "@react-navigation/native";import { createStackNavigator } from "@react-navigation/stack";import ListScreen from "../screens/ListScreen";import ModalScreen from "../screens/ModalScreen";const Stack = createStackNavigator();function MainStackNavigator() {return (<NavigationContainer><Stack.Navigatormode="modal"headerMode="none"screenOptions={{cardStyle: { backgroundColor: "transparent" },cardOverlayEnabled: true,cardStyleInterpolator: ({ current: { progress } }) => ({cardStyle: {opacity: progress.interpolate({inputRange: [0, 0.5, 0.9, 1],outputRange: [0, 0.25, 0.7, 1],}),},overlayStyle: {opacity: progress.interpolate({inputRange: [0, 1],outputRange: [0, 0.5],extrapolate: "clamp",}),},}),}}><Stack.Screen name="List" component={ListScreen} /><Stack.Screen name="Modal" component={ModalScreen} /></Stack.Navigator></NavigationContainer>);}export default MainStackNavigator;


5. src/screens/ListScreen.js

import React from "react";import {StyleSheet,StatusBar,Text,View,TouchableOpacity,FlatList,} from "react-native";import { Ionicons } from "@expo/vector-icons";import { useSelector, useDispatch } from "react-redux";import { removeItem } from "../redux/reducer";import Header from "../components/Header";function ListScreen({ navigation }) {return (<><StatusBar barStyle="light-content" /><View style={styles.container}><Header title={"List"} /><ListView /><View style={styles.fabContainer}><TouchableOpacityonPress={() => navigation.navigate("Modal")}style={styles.fabButton}><Ionicons name="ios-add" color="#fff" size={70} /></TouchableOpacity></View></View></>);}function ListView() {const listItems = useSelector((state) => state.itemList);console.log({ listItems });const dispatch = useDispatch();return (<Viewstyle={{backgroundColor: "white",flex: 1,borderTopLeftRadius: 20,borderTopRightRadius: 20,paddingHorizontal: 20,paddingVertical: 20,}}>{listItems.length !== 0 ? (<FlatListdata={listItems}keyExtractor={(item) => item.id.toString()}renderItem={({ item }) => (<View style={styles.listItemContainer}><Text style={styles.itemTitle} numberOfLines={1}>{item.name}</Text><TouchableOpacityonPress={() => dispatch(removeItem(item.id))}style={styles.button}><Ionicons name="ios-trash" color="#fff" size={20} /></TouchableOpacity></View>)}/>) : (<Text style={{ fontSize: 30 }}>You list is empty :'(</Text>)}</View>);}const styles = StyleSheet.create({container: {flex: 1,backgroundColor: "blue",},fabContainer: {justifyContent: "flex-end",flexDirection: "row",position: "absolute",right: 10,bottom: 20,},fabButton: {backgroundColor: "blue",borderRadius: 35,width: 70,height: 70,alignItems: "center",justifyContent: "center",},listItemContainer: {flex: 1,flexDirection: "row",paddingTop: 10,paddingBottom: 5,paddingRight: 5,justifyContent: "space-between",width: "100%",borderBottomWidth: 0.25,},itemTitle: {fontSize: 22,fontWeight: "400",},button: {borderRadius: 8,backgroundColor: "#ff333390",padding: 5,},});export default ListScreen;


6. src/screens/ModalScreen.js

import React, { useState, useCallback } from "react";import {StyleSheet,Text,View,TouchableOpacity,TextInput,} from "react-native";import { Ionicons } from "@expo/vector-icons";import { useDispatch } from "react-redux";import { addItem } from "../redux/reducer";function ModalScreen({ navigation }) {const [value, setValue] = useState("");const dispatch = useDispatch();const onSaveNote = (value) => {dispatch(addItem(value));navigation.navigate("List");};return (<View style={styles.container}><View style={styles.innerContainer}><View style={styles.closeButtonContainer}><TouchableOpacitystyle={styles.closeButton}onPress={() => navigation.goBack()}><Ionicons name="ios-close" color="#101010" size={40} /></TouchableOpacity></View><View style={styles.modalContainer}><Text style={{ color: "#444", fontSize: 20 }}>What do you want to do?</Text><TextInputstyle={{height: 50,width: 200,padding: 5,borderColor: "gray",borderBottomWidth: 1,}}numberOfLines={1}onChangeText={(value) => setValue(value)}value={value}clearButtonMode="while-editing"/><TouchableOpacitystyle={{marginTop: 10,backgroundColor: "blue",width: 50,height: 50,alignItems: "center",justifyContent: "center",borderRadius: 5,}}onPress={() => onSaveNote(value)}><Ioniconsname="ios-arrow-dropright-circle"size={40}color="#fff"/></TouchableOpacity></View></View></View>);}const styles = StyleSheet.create({container: {flex: 1,},innerContainer: {borderTopLeftRadius: 10,borderTopRightRadius: 10,justifyContent: "flex-end",flexDirection: "row",height: "30%",width: "100%",position: "absolute",bottom: 0,right: 0,backgroundColor: "#fff",},closeButtonContainer: {position: "absolute",alignItems: "flex-end",right: 10,},closeButton: {backgroundColor: "#d3d3d3",borderRadius: 20,width: 40,height: 40,top: 10,alignItems: "center",justifyContent: "center",},modalContainer: {justifyContent: "center",alignItems: "center",position: "absolute",margin: 60,top: 10,left: 50,},});export default ModalScreen;


7. App.js

import React from "react";import { Provider as StateProvider } from "react-redux";import store from "./src/redux/store";import MainStackNavigator from "./src/navigation/AppNavigator";export default function App() {return (<StateProvider store={store}><MainStackNavigator /></StateProvider>);}

19. The final output of the demo application

Here is the final output of the demo app:

That’s all about in this article.


Conclusion

In this article, we understood how to use Redux with React Hooks by building a real React Native application. This article showed the demo code step by step to use Redux with React Hooks by building a real React Native application. The addition to hooks in react-redux such as useSelector and useDispatch reduces the need to write plentiful boilerplate code and also provides the advantage to use functional components. We also discussed better understanding of the basics of react navigation in real React native application.

Thanks for reading! I hope you enjoyed and learned about Redux and React Hooks practical usage in React Native application. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow official website and tutorials of React Native as below links :

React Native Official Website

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING!!???

React Native – How To Handle Deep Linking in React Native ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (How To Handle Deep Linking in React Native ?).

In this article, We will learn how to handle deep linking in react native. Mobile apps have a unique vulnerability that is non-existent in the web: Deep Linking. Deep Linking is a technique in which a given URL or resource is used to open a specific page or screen on mobile. So, instead of just launching the app on mobile, a deep link can lead a user to a specific page within the app, providing a better experience. This specific page or screen may reside under a series of hierarchical pages, hence the term “deep” in deep linking.

Deep linking is a way of sending data directly to a native application from an outside source. A deep link looks like app:// where app is our app scheme and anything following the // could be used internally to handle the request. As a user, we probably have experienced deep linking when opening a link to a product in a browser. If we have the app of that shop installed, it may use a deep link to open the app on that product’s page.

For example, if we were building an e-commerce app, we could use app://products/1 to deep link to our app and open the product detail page for a product with id 1. We can think of these kind of like URLs on the web.

Deep linking consists of using a uniform resource identifier (URI) that links to a specific location within a mobile app rather than simply launching the app. Deferred deep linking allows users to deep link to content even if the app is not already installed.

In this article, we will discuss a React Native app that opens a specific page based on the URI provided from an external source.

A famous quote about learning is :

” The beautiful thing about learning is nobody can take it away from you. “

So Let’s begin.


Why Deep Linking?

Deep Link has many use cases where it can come very handy. Think of marketing strategies, referral links, sharing a certain product, etc. The greatest benefit of mobile deep linking is the ability for marketers and app developers to bring users directly into the specific location within their app with a dedicated link. Just as deep links made the web more usable, mobile deep links do the same for mobile apps.


Example

Let’s try to mimic a React Native demo app that opens a specific page based on the URI provided from an external source. To handle deep links, we are going to use an optimum solution provided by the react-navigation library.


Configure react-navigation in a React Native App

To start, we create a new React Native project by running the following command:

react-native init rnDeepLinkingDemo

cd rnDeepLinkingDemo

To be able to support deep linking via the navigation, we add the required npm dependencies. Once the project directory has been generated from the above command, navigate inside the project folder from our terminal and install the following dependencies.

npm install react-navigation --save

npm install react-native-gesture-handler react-native-safe-area-context @react-native-community/masked-view react-native-screens react-native-reanimated --save

npm install react-navigation-stack --save

The next step is to link all the libraries we just installed. From React Native 0.60 and higher, linking is automatic. So we don’t need to run react-native link.

On iOS devices, we just have to run the following set of commands.

cd ios
pod install
cd ..

For Android devices, we add the following lines to the android/app/build.gradle file under the dependencies section:

implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha02'

Then, open the android/app/src/main/java/com/rndeeplinkdemo/MainActivity.java file and add the following snippet:

package com.rndeeplinkingdemo;

import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;

public class MainActivity extends ReactActivity {

  /**
   * Returns the name of the main component registered from JavaScript. This is used to schedule
   * rendering of the component.
   */
  @Override
  protected String getMainComponentName() {
    return "RNDeepLinkingDemo";
  }

  protected ReactActivityDelegate createReactActivityDelegate() {
    return new ReactActivityDelegate(this, getMainComponentName()) {
        @Override
        protected ReactRootView createRootView() {
            return new RNGestureHandlerEnabledRootView(MainActivity.this);
        }
    };
  }

}


Create a Home & Details Screen

We are going to create all the screens for this example inside the directory src/screens. To start with the home screen, create a new file Home.js inside the aforementioned path.

This screen is going to render a list of users from an array of mock data from a placeholder API using a FlatList component. Each user is going to be wrapped inside a TouchableOpacity. The reason being, when an end-user presses a username from the list, this is going to contain the logic for navigating from the Home screen to the Details screen (which we will add later).

import React, {useState, useEffect} from 'react';
import {View, Text, FlatList, TouchableOpacity} from 'react-native';

function Home({navigation}) {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/users')
      .then((res) => res.json())
      .then((res) => {
        setData(res);
      })
      .catch((error) => {
        console.log(error);
      });
  }, []);

  const Separator = () => (
    <View
      style={{
        borderBottomColor: '#d3d3d3',
        borderBottomWidth: 1,
        marginTop: 10,
        marginBottom: 10,
      }}
    />
  );
  return (
    <View style={{flex: 1}}>
      <View style={{paddingHorizontal: 20, paddingVertical: 20}}>
        <FlatList
          data={data}
          keyExtractor={(item) => item.id.toString()}
          ItemSeparatorComponent={Separator}
          renderItem={({item}) => (
            <TouchableOpacity
              onPress={() => navigation.navigate('Details', {item})}>
              <Text style={{fontSize: 24}}>{item.name}</Text>
            </TouchableOpacity>
          )}
        />
      </View>
    </View>
  );
}
export default Home;

For the details screen, for now, let us display user list details. We create a new file called Details.js. To display information for each user when visiting the Details screen, we have to pass the value of each item using navigation parameters. Next, To fetch the data from the placeholder API on initial render, let us use the useEffect hook from React. This hook is going to behave like a good old lifecycle method componentDidMount(). It also allows that if the full item object is passed or not. If not, just grab the userId and request the API. Then, define a state variable data to store the incoming user information. Also, modify the contents of return in this component screen.

import React, {useState, useEffect} from 'react';
import {View, Text} from 'react-native';

function Details({navigation}) {
  const [data, setData] = useState([]);

  useEffect(() => {
    const item = navigation.getParam('item', {});

    if (Object.keys(item).length === 0) {
      const userId = navigation.getParam('userId', 1);
      fetch(`https://jsonplaceholder.typicode.com/users/${userId}`)
        .then((res) => res.json())
        .then((res) => {
          const data = [];

          Object.keys(res).forEach((key) => {
            data.push({key, value: `${res[key]}`});
          });

          setData(data);
        });
    } else {
      const data = [];

      Object.keys(item).forEach((key) => {
        data.push({key, value: `${item[key]}`});
      });

      setData(data);
    }
  }, []);

  return (
    <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
      {data.map((data) => (
        <Text
          style={{fontSize: 20}}
          key={data.key}>{`${data.key}: ${data.value}`}</Text>
      ))}
    </View>
  );
}

export default Details;


Configure Deep Linking in React Navigation

To navigate from Home to Details screen, we need Stack Navigator from react-navigation. We create a new file called index.js inside the src/navigation directory and import the following statements.

import React from 'react'
import { createAppContainer, createSwitchNavigator } from 'react-navigation'
import { createStackNavigator } from 'react-navigation-stack'
import Home from '../screens/Home'
import Details from '../screens/Details'

Create a stack navigator with Home as the initial screen. To enable deep linking, the current app requires an identifier to recognize the URI path from the external source to the screen of the app. The library react-navigation provides a path attribute for this. It tells the router relative path to match against the URL. We configure both the routes as follows:

const MainApp = createStackNavigator({
  Home: {
    screen: Home,
    navigationOptions: {
      headerTitle: 'Home',
    },
    path: 'home',
  },
  Details: {
    screen: Details,
    navigationOptions: {
      headerTitle: 'Details',
    },
    path: 'details/:userId',
  },
});

In the above snippet, the dynamic variable specified by :userId is passed to details/. This is going to allow the app to accept a dynamic value such as details/1234.

Next, we add the configuration to the navigation to extract the path from the incoming URL from the external resource. This is done by uriPrefix. Add the following code snippet at the end of the file:

export default () => {
  const prefix = 'myapp://';
  return <AppContainer uriPrefix={prefix} />;
};

The full code of index.js file is as below :

import React from 'react';
import {createAppContainer} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import Home from '../screens/Home';
import Details from '../screens/Details';

const MainApp = createStackNavigator({
  Home: {
    screen: Home,
    navigationOptions: {
      headerTitle: 'Home',
    },
    path: 'home',
  },
  Details: {
    screen: Details,
    navigationOptions: {
      headerTitle: 'Details',
    },
    path: 'details/:userId',
  },
});

const AppContainer = createAppContainer(MainApp);

export default () => {
  const prefix = 'myapp://';
  return <AppContainer uriPrefix={prefix} />;
};

Import this navigation module inside the App.js file for it to work:

import React from 'react';
import AppContainer from './src/navigation';

const App = () => {
  return <AppContainer />;
};

export default App;


Configure URI Scheme For Native iOS Apps

To make this work, we have to configure the native iOS and Android app to open URLs based on the prefix myapp://.

For iOS devices, open the ios/rnDeepLinkDemo/AppDelegate.m file and add the following.

// Add the header at the top of the file:
#import <React/RCTLinkingManager.h>
// Add this above the `@end`:
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
 options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
 return [RCTLinkingManager application:app openURL:url options:options];
}

Open ios/rnDeepLinkingDemo.xcodeproj in the Xcode app and select the app from the left navigation bar.

Open the Info tab.

Next, go to the URL Types.

Click the + button and in identifier as well as URL schemes add myapp.

Rebuild the React Native binaries by running react-native run-ios.

For Android users, we have to configure the external linking as well. Open /android/app/src/main/AndroidManifest.xml and set the value of launchMode to singleTask. Also, add a new intent-filter:

<activity
 android:name=".MainActivity"
 <!--set the below value-->
 android:launchMode="singleTask">
 <intent-filter>
 <action android:name="android.intent.action.MAIN" />
 <category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>
 <!--Add the following-->

 <intent-filter>
 <action android:name="android.intent.action.VIEW" />
 <category android:name="android.intent.category.DEFAULT" />
 <category android:name="android.intent.category.BROWSABLE" />
 <data android:scheme="myapp" />
 </intent-filter>
</activity>

Let’s understand the intent-filter a little better.

An intent filter is an expression in an app’s manifest file that specifies the type of intents that the component would like to receive.

Get a closer look on <data> tag inside <intent-filter>. There are two properties that we have to care about. Consider scheme as a type of incoming link and host as the URL.

Our Deep Link will look something like this: myapp://home .


Testing The App

Before we run the app on our platform of choice, make sure to re-build it using the specific command for the mobile OS as below:

# ios
react-native run-ios

# android
react-native run-android

The Example app output is going to be like below.

To test deep link in iOS, we open a web browser in our iOS simulator device and run the URL myapp://home. It is going to ask us to whether open the external URI in the app . Next, try entering the URL myapp://details/1 and see what happens.

To test deep link in Android, we make sure our android app is in background and run this command:

adb shell am start -W -a android.intent.action.VIEW -d myapp://home com.rndeeplinkingdemo

adb shell am start -W -a android.intent.action.VIEW -d myapp://details/1 com.rndeeplinkingdemo

If our package has a different name then edit command as follows:

$ adb shell am start -W -a android.intent.action.VIEW -d <URI> <PACKAGE>

If our App opened successfully then our Deep Linking is working as expected.

That’s all about in this article.


Conclusion

In this article, We understood how to handle Deep Linking in React Native. We also discussed about a complete demo of a React Native app that handles deep linking using react-navigation. Deep linking can bring significant improvements to the user experience of our mobile apps and enable search engines to provide context-sensitive searches and results.

Thanks for reading ! I hope you enjoyed and learned about the Deep Linking Concepts in React Native. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow official website and tutorials of React Native as below links :

React Native Official Website

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING!!???

React Native – How To Manage The Lifecycle of Gestures In React Native ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (How To Manage The Lifecycle of Gestures In React Native ?).

In this article, We will learn how to manage the lifecycle of gestures in react native. The gesture responder system manages the lifecycle of gestures in react native application. A touch can go through several phases as the app determines what the user’s intention is. For example, the app needs to determine if the touch is scrolling, sliding on a widget, or tapping. This can even change during the duration of a touch. There can also be multiple simultaneous touches.

The touch responder system is needed to allow components to negotiate these touch interactions without any additional knowledge about their parent or child components.

A famous quote about learning is :

” Change is the end result of all true learning. “

So Let’s begin.


Best Practices

To make our app feel great, every action should have the following attributes:

  • Feedback/highlighting – show the user what is handling their touch, and what will happen when they release the gesture
  • Cancel-ability – when making an action, the user should be able to abort it mid-touch by dragging their finger away

These features make users more comfortable while using an app, because it allows people to experiment and interact without fear of making mistakes.


TouchableHighlight and Touchable

The responder system can be complicated to use. So we have provided an abstract Touchable implementation for things that should be “tappable“. This uses the responder system and allows us to configure tap interactions declaratively. Use TouchableHighlight anywhere where we would use a button or link on web.


Gesture Responder System Lifecycle

A view can become the touch responder by implementing the correct negotiation methods. There are two methods to ask the view if it wants to become responder:

  • View.props.onStartShouldSetResponder: (evt) => true, – Does this view want to become responder on the start of a touch?
  • View.props.onMoveShouldSetResponder: (evt) => true, – Called for every touch move on the View when it is not the responder: does this view want to “claim” touch responsiveness?

If the View returns true and attempts to become the responder, one of the following will happen:

  • View.props.onResponderGrant: (evt) => {} – The View is now responding for touch events. This is the time to highlight and show the user what is happening.
  • View.props.onResponderReject: (evt) => {} – Something else is the responder right now and will not release it.

If the view is responding, the following handlers can be called:

  • View.props.onResponderMove: (evt) => {} – The user is moving their finger.
  • View.props.onResponderRelease: (evt) => {} – Fired at the end of the touch, ie “touchUp”.
  • View.props.onResponderTerminationRequest: (evt) => true – Something else wants to become responder. Should this view release the responder? Returning true allows release.
  • View.props.onResponderTerminate: (evt) => {} – The responder has been taken from the View. Might be taken by other views after a call to onResponderTerminationRequest, or might be taken by the OS without asking (happens with control center/ notification center on iOS).

evt is a synthetic touch event with the following nativeEvent form:

  • changedTouches – Array of all touch events that have changed since the last event
  • identifier – The ID of the touch
  • locationX – The X position of the touch, relative to the element
  • locationY – The Y position of the touch, relative to the element
  • pageX – The X position of the touch, relative to the root element
  • pageY – The Y position of the touch, relative to the root element
  • target – The node id of the element receiving the touch event
  • timestamp – A time identifier for the touch, useful for velocity calculation
  • touches – Array of all current touches on the screen


Capture ShouldSet Handlers

onStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern, where the deepest node is called first. That means that the deepest component will become responder when multiple Views return true for ShouldSetResponder handlers. This is desirable in most cases, because it makes sure all controls and buttons are usable.

However, sometimes a parent will want to make sure that it becomes responder. This can be handled by using the capture phase. Before the responder system bubbles up from the deepest component, it will do a capture phase, firing on ShouldSetResponderCapture. So if a parent View wants to prevent the child from becoming responder on a touch start, it should have a onStartShouldSetResponderCapture handler which returns true.

  • View.props.onStartShouldSetResponderCapture: (evt) => true,
  • View.props.onMoveShouldSetResponderCapture: (evt) => true,


Pan Responder

PanResponder reconciles several touches into a single gesture. It makes single-touch gestures resilient to extra touches, and can be used to recognize basic multi-touch gestures.

By default, PanResponder holds an InteractionManager handle to block long-running JS events from interrupting active gestures.

It provides a predictable wrapper of the responder handlers provided by the gesture responder system. For each handler, it provides a new gestureState object alongside the native event object:

onPanResponderMove: (event, gestureState) => {}

A native event is a synthetic touch event with form of PressEvent.

gestureState object has the following:

  • stateID – ID of the gestureState- persisted as long as there at least one touch on screen
  • moveX – the latest screen coordinates of the recently-moved touch
  • moveY – the latest screen coordinates of the recently-moved touch
  • x0 – the screen coordinates of the responder grant
  • y0 – the screen coordinates of the responder grant
  • dx – accumulated distance of the gesture since the touch started
  • dy – accumulated distance of the gesture since the touch started
  • vx – current velocity of the gesture
  • vy – current velocity of the gesture
  • numberActiveTouches – Number of touches currently on screen


API

Only a single component can respond to touch events at one time – the component responding to events owns a global “interaction lock”. The PanResponder API helps us manage what component owns this lock through a set of callbacks. Each of these callbacks is also passed an event and gestureState object containing info about the touch events (e.g. position and velocity).

To create a PanResponder, we call PanResponder.create(callbacksObject). The result is a set of props that can be passed to View as props (these are the lower-level touch event handling props). We’ll typically wrap the result with useRef, since we only want to create a single PanResponder for the lifecycle of the component.

The full set of callbacks we can pass is:

  • onStartShouldSetPanResponder: (event, gestureState) => {}
  • onStartShouldSetPanResponderCapture: (event, gestureState) => {}
  • onMoveShouldSetPanResponder: (event, gestureState) => {}
  • onMoveShouldSetPanResponderCapture: (event, gestureState) => {}
  • onPanResponderReject: (event, gestureState) => {}
  • onPanResponderGrant: (event, gestureState) => {}
  • onPanResponderStart: (event, gestureState) => {}
  • onPanResponderEnd: (event, gestureState) => {}
  • onPanResponderRelease: (event, gestureState) => {}
  • onPanResponderMove: (event, gestureState) => {}
  • onPanResponderTerminate: (event, gestureState) => {}
  • onPanResponderTerminationRequest: (event, gestureState) => {}
  • onShouldBlockNativeResponder: (event, gestureState) => {}


Usage Pattern

const ExampleComponent = () => {
  const panResponder = React.useRef(
    PanResponder.create({
      // Ask to be the responder:
      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onStartShouldSetPanResponderCapture: (evt, gestureState) =>
        true,
      onMoveShouldSetPanResponder: (evt, gestureState) => true,
      onMoveShouldSetPanResponderCapture: (evt, gestureState) =>
        true,

      onPanResponderGrant: (evt, gestureState) => {
        // The gesture has started. Show visual feedback so the user knows
        // what is happening!
        // gestureState.d{x,y} will be set to zero now
      },
      onPanResponderMove: (evt, gestureState) => {
        // The most recent move distance is gestureState.move{X,Y}
        // The accumulated gesture distance since becoming responder is
        // gestureState.d{x,y}
      },
      onPanResponderTerminationRequest: (evt, gestureState) =>
        true,
      onPanResponderRelease: (evt, gestureState) => {
        // The user has released all touches while this view is the
        // responder. This typically means a gesture has succeeded
      },
      onPanResponderTerminate: (evt, gestureState) => {
        // Another component has become the responder, so this gesture
        // should be cancelled
      },
      onShouldBlockNativeResponder: (evt, gestureState) => {
        // Returns whether this component should block native components from becoming the JS
        // responder. Returns true by default. Is currently only supported on android.
        return true;
      }
    })
  ).current;

  return <View {...panResponder.panHandlers} />;
};


Example

PanResponder works with Animated API to help build complex gestures in the UI. The following example contains an animated View component which can be dragged freely across the screen.

import React, { useRef } from "react";
import { Animated, View, StyleSheet, PanResponder, Text } from "react-native";

const App = () => {
  const pan = useRef(new Animated.ValueXY()).current;

  const panResponder = useRef(
    PanResponder.create({
      onMoveShouldSetPanResponder: () => true,
      onPanResponderGrant: () => {
        pan.setOffset({
          x: pan.x._value,
          y: pan.y._value
        });
      },
      onPanResponderMove: Animated.event(
        [
          null,
          { dx: pan.x, dy: pan.y }
        ]
      ),
      onPanResponderRelease: () => {
        pan.flattenOffset();
      }
    })
  ).current;

  return (
    <View style={styles.container}>
      <Text style={styles.titleText}>Drag this box!</Text>
      <Animated.View
        style={{
          transform: [{ translateX: pan.x }, { translateY: pan.y }]
        }}
        {...panResponder.panHandlers}
      >
        <View style={styles.box} />
      </Animated.View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center"
  },
  titleText: {
    fontSize: 14,
    lineHeight: 24,
    fontWeight: "bold"
  },
  box: {
    height: 150,
    width: 150,
    backgroundColor: "blue",
    borderRadius: 5
  }
});

export default App;

The output of the above example is :

That’s all about in this article.


Conclusion

In this article, We understood how to manage the lifecycle of gestures in react native. We also discussed about Best Practices and PanResponser usage in React Native platform.

Thanks for reading ! I hope you enjoyed and learned about the Gestures Concepts in React Native. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow official website and tutorials of React Native as below links :

React Native Official Website

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING!!???

React Native – How To Navigate Between Screens In React Native ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (How To Navigate Between Screens In React Native ?).

In this article, We will learn how to navigate between screens in react native. Mobile apps are rarely made up of a single screen. Managing the presentation of, and transition between, multiple screens is typically handled by what is known as a navigator. This article covers the various navigation components available in React Native. If we are getting started with navigation, we will probably want to use React Navigation. React Navigation provides a straightforward navigation solution, with the ability to present common stack navigation and tabbed navigation patterns on both Android and iOS.

If we’d like to achieve a native look and feel on both Android and iOS, or we’re integrating React Native into an app that already manages navigation natively, the following library provides native navigation on both platforms: react-native-navigation.

A famous quote about learning is :

” Study hard what interests you the most in the most undisciplined, irreverent and original manner possible. “

So Let’s begin.


Overview

The community solution to navigation is a standalone library that allows developers to set up the screens of an app with a few lines of code.

React Navigation is the most popular navigation library. It handles most of the challenges described above nicely, and is sufficiently configurable for most apps.

React Navigation provides all the different type of navigator like

  • Stack Navigator : For the simple screen switching
  • Drawer Navigator : To create Navigation Drawer/ Sidebar
  • Bottom Tab Navigator : For the bottom navigation
  • Top Tab Navigator : To create the tab navigation


Navigation Challenges

There are a few aspects of navigation which make it challenging in React Native:

  • Navigation works differently on each native platform. iOS uses view controllers, while android uses activities. These platform-specific APIs work differently technically and appear differently to the user. React Native navigation libraries try to support the look-and-feel of each platform, while still providing a single consistent JavaScript API.
  • Native navigation APIs don’t correspond with “views”. React Native components like ViewText, and Image, roughly map to an underlying native “view”, but there isn’t really an equivalent for some of the navigation APIs. There isn’t always a clear way to expose these APIs to JavaScript.
  • Navigation on mobile is stateful. On the web, navigation is typically stateless, where a url (i.e. route) takes a user to a single screen/page. On mobile, the history of the user’s navigation state is persisted in the application so that the user can go back to previous screens – a stack of screens can even include the same screen multiple times.

Due to these challenges, there isn’t a single best way to implement navigation, so it was removed from the core React Native package.


Installation and Setup

First, we need to install them in our project:

npm install @react-navigation/native @react-navigation/stack

Next, we install the required peer dependencies. We need to run different commands depending on whether our project is an Expo managed project or a bare React Native project.

  • If we have an Expo managed project, install the dependencies with expo:
expo install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
  • If we have a bare React Native project, install the dependencies with npm:
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

For iOS with bare React Native project, make sure we have Cocoapods installed. Then we install the pods to complete the installation:

cd ios
pod install
cd ..

We might get warnings related to peer dependencies after installation. They are usually caused by incorrect version ranges specified in some packages. We can safely ignore most warnings as long as our app builds.

To finalize installation of react-native-gesture-handler, add the following at the top (make sure it’s at the top and there’s nothing else before it) of our entry file, such as index.js or App.js:

import 'react-native-gesture-handler';

Now, we need to wrap the whole app in NavigationContainer. Usually we’d do this in our entry file, such as index.js or App.js :

import 'react-native-gesture-handler';
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';

const App = () => {
  return (
    <NavigationContainer>
      {/* Rest of app code */}
    </NavigationContainer>
  );
};

export default App;

Now we are ready to build and run our app on the device/simulator.


Steps For Adding React Navigation To The App

In this section, we’ll walk through adding react-navigation to an app.

After install the required dependencies, we need to do 3 things:

  • Set up a <NavigationContainer> from @react-navigation/native
  • Create a navigator:
    • createStackNavigator from @react-navigation/stack
    • createBottomTabNavigator from @react-navigation/bottom-tabs
    • createDrawerNavigator from @react-navigation/drawer
  • Define the screens in our app


1. Create a navigator

We first choose one of the available navigators, e.g. stack, which will act as our root navigator. Navigators may be nested later.

import { createStackNavigator } from '@react-navigation/stack'

const Root = createStackNavigator()


2. Create screen components

Next, we create a component for each screen.

Screens are regular React components. They’ll be passed navigation-specific props when instantiated.

const Screen1 = ({ navigation, route }) => {
  return <Text>Screen1</Text>
}


3. Render it

Lastly, we render a NavigationContainer with our navigator within it.

Each Screen component defines a route in our app. If we want nested navigators, e.g. a tab navigator within a stack navigator, we can use another navigator as a screen’s component. We only need a single NavigationContainer, even if we have nested navigators.

import { NavigationContainer } from '@react-navigation/native'

// ...

const App = () => {
  return (
    <NavigationContainer>
      <Root.Navigator>
        <Root.Screen name="Screen1" component={Screen1} />
        <Root.Screen name="Screen2" component={Screen2} />
        <Root.Screen name="Screen3" component={Screen3} />
      </Root.Navigator>
    </NavigationContainer>
  )
}


Navigating and Routes

Each navigator supports different ways of navigating:

  • Stack: push
  • Tabs: navigate
  • Drawer: openDrawer

When navigating, we typically specify a screen name and optionally parameters, e.g. navigator.push("Screen2", { paramA: "Hello!" }).


Navigation

In this example, we navigate from Screen1 to Screen2 by pushing Screen2 onto the stack when a button is pressed.

const Screen1 = ({ navigation }) => {
  return (
    <Button
      onPress={() => {
        navigation.push('Screen2', { paramA: 'Hello!' })
      }}
    />
  )
}


Routes

Within a screen, we have access to the current route and it’s parameters.

const Screen2 = ({ route }) => {
  return <Text>{route.params.paramA}</Text>
}


Hooks

For components which aren’t screens (direct descendants of a navigator), we can access the navigation and route objects using hooks. Some developers prefer using these hooks instead of props, even in screen components.

import { useNavigation, useRoute } from '@react-navigation/native'

const Screen1 = () => {
  const navigation = useNavigation()
  const route = useRoute()

  // ...
}


Usage

Now we can create an app with a home screen and a profile screen:

import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

const Stack = createStackNavigator();

const MyStack = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          name="Home"
          component={HomeScreen}
          options={{ title: 'Welcome' }}
        />
        <Stack.Screen name="Profile" component={ProfileScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

In this example, there are 2 screens (Home and Profile) defined using the Stack.Screen component. Similarly, we can define as many screens as we like.

We can set options such as the screen title for each screen in the options prop of Stack.Screen.

Each screen takes a component prop that is a React component. Those components receive a prop called navigation which has various methods to link to other screens. For example, we can use navigation.navigate to go to the Profile screen:

const HomeScreen = ({ navigation }) => {
  return (
    <Button
      title="Go to Jane's profile"
      onPress={() =>
        navigation.navigate('Profile', { name: 'Jane' })
      }
    />
  );
};
const ProfileScreen = () => {
  return <Text>This is Jane's profile</Text>;
};

The views in the stack navigator use native components and the Animated library to deliver 60fps animations that are run on the native thread. Plus, the animations and gestures can be customized.

React Navigation also has packages for different kind of navigators such as tabs and drawer. We can use them to implement various patterns in our app.

That’s all about in this article.


Conclusion

In this article, We understood how to navigate between screens in react native. We also discussed about navigation challenges, dependencies and navigation usage in React Native platform.

Thanks for reading ! I hope you enjoyed and learned about the Navigation Concepts in React Native. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow official website and tutorials of React Native as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING!!???

A Short Note – Functional vs Class Components in React Native

Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (Functional vs Class Components in React Native).

In this note series, we will understand about the difference between Functional and Class Components in React Native.

So Let’s begin.

In React Native, there are two main types of components that make up an application: functional components and class components. These are structured the same as they would be in a regular React app for the web.


Class Components vs Functional Components


1. Syntax

Class components are JavaScript ES2015 classes that extend a base class from React called Component and create a render function that returns a React element. This requires more code as well.

The Class Component in React Native

class App extends Component {
    render () {
        return (
            <Text>Hello World!</Text>
        )
    }
}
export default App;

A Functional Component looks like a plain JavaScript function and are sometimes called stateless components.

The Functional Component in React Native

const App = () =>{
	return (
	  <Text>Hello World!</Text>
	)
}
export default App;


2. State

In Class components, there is a way to store and manage state built in to React Native. This gives the class App access to the React life cycle methods like render as well as state/props functionality from the parent. While managing the state in classes, we use setState and this.state to set and get the state, respectively.

State in Class Component

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

class App extends React.Component {
	constructor(props){
		super(props);
		this.state = { value:0};
		setInterval(() =>{
			this.setState({ value: this.state.value + 1});
		}, 1000);
	}

	render() {
		return (
			<View>
				<Text>{'State Value =>' + this.state.value}</Text>
			</View>
		);

	}
}

export default App;

But in the functional component, we have useState hook after the update of React 16.8. They don’t manage their own state by React Native.

State in Functional Component

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

const App = () => {
		let [value, setValue] = useState(0);
		
		setInterval(() =>{
			setValue(value + 1);
		}, 1000);
	
		return (
			<View>
				<Text>{'State Value =>' + value}</Text>
			</View>
		);
};

export default App;


3. Lifecycle Methods/Hooks

Another most important difference in Class and Functional Component is the life cycle methods, or we can say Lifecycle Hooks. We all know how important is the Lifecycle methods while developing any React Native application. Life cycle methods give us the power to control the data and application flow on different activities. We are very much familiar with the class component Lifecycle methods but in case of Functional Components we have to manage all this with the help of useEffect hook.

Example of Lifecycle Methods for Class Component

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

export default class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    }
  }

  componentDidMount() {
    const interval = setTimeout(() => {
      this.setState({ count: this.state.count + 1 });
    }, 1000);
    return () => {
      clearInterval(this.interval);
    }
  }

  render() {
    return (
      <View style={styles.container}>
        <Text> Count incremented {this.state.count} times</Text>
      </View>
    );
  }
}

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

Example of useEffect Hook for Functional Component

import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount
  useEffect(() => {
    const interval = this.setTimeout(() => {
      setCount(count + 1);
    }, 1000);
    return () => {
      clearInterval(this.interval);
    }
  }, []);

  return (
    <View style={styles.container}>
      <Text> Count incremented {count} times</Text>
    </View>
  );
}

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


Conclusion

In this note series, we understood about the difference between Functional and Class Components in React Native. We conclude that :

  • Class components are used as container components to handle state management and wrap child components.
  • Functional components are just used for display purposes – these components call functions from parent components to handle user interactions or state updates. 

Thanks for reading! I hope you enjoyed and learned about Functional Vs Class Components Concepts in React Native. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe to the blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow official website and tutorials of React Native as below links :

If you have any comments, questions, or think I missed something, leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

ReactJS – Jest Framework – The Most Valuable Concepts Improve Code Quality

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will talk about the ins and outs of Jest to help you get started with testing. we will learn more about the vocabulary associated with Jest testing, like mocks and spies. Also, we’ll cover some of the basics of Jest testing, like using describe blocks and the keywords it and expect. Finally, we’ll take a look at snapshot testing and why it’s particularly useful for front-end testing.

A famous quote about learning is :

The more I live, the more I learn. The more I learn, the more I realizes, the less I know.


So Let’s start.


What Is Jest?

Jest was created by Facebook specifically for testing React applications. It’s one of the most popular ways of testing React components. Since its introduction, the tool has gained a lot of popularity. This popularity has led to the use of Jest for testing both JavaScript front-end and back-end applications. Many large companies—including Twitter, Instagram, Pinterest, and Airbnb—use Jest for React testing.

Jest itself is actually not a library but a framework. There’s even a CLI tool that you can use from the command line. To give an example, the CLI tool allows you to run only specific tests that match a pattern. Besides that, it hosts much more functionality, which you can find in the CLI documentation.

Jest offers a test runner, assertion library, CLI tool, and great support for different mocking techniques. All of this makes it a framework and not just a library.


Jest Characteristics

From the JestJS.io website, we can find four main characteristics of Jest:

  • Zero config: “Jest aims to work out of the box, config free, on most JavaScript projects.” This means you can simply install Jest as a dependency for your project, and with no or minimal adjustments, you can start writing your first test.
  • Isolated: Isolation is a very important property when running tests. It ensures that different tests don’t influence each other’s results. For Jest, tests are executed in parallel, each running in their own process. This means they can’t interfere with other tests, and Jest acts as the orchestrator that collects the results from all the test processes.
  • Snapshots: Snapshots are a key feature for front-end testing because they allow you to verify the integrity of large objects. This means you don’t have to write large tests full of assertions to check if every property is present on an object and has the right type. You can simply create a snapshot and Jest will do the magic. Later, we’ll discuss in detail how snapshot testing works.
  • Rich API: Jest is known for having a rich API offering a lot of specific assertion types for very specific needs. Besides that, its great documentation should help you get started quickly.


Jest Vocabulary

Mock

From the Jest documentation, we can find the following description for a Jest mock: 

“Mock functions make it easy to test the links between code by erasing the actual implementation of a function, capturing calls to the function (and the parameters passed in those calls).”

In addition, we can use a mock to return whatever we want it to return. This is very useful to test all the paths in our logic because we can control if a function returns a correct value, wrong value, or even throws an error.

In short, a mock can be created by assigning the following snippet of code to a function or dependency:

jest.fn()

Here’s an example of a simple mock, where we just check whether a mock has been called. We mock mockFn and call it. Thereafter, we check if the mock has been called:

const mockFn = jest.fn();
mockFn();
expect(mockFn).toHaveBeenCalled();

The following example also mocks a return value for checking specific business logic. We mock the returnsTrue function and let it return false:

const returnsTrue = jest.fn(() => false);
console.log(returnsTrue()); // false;

Spy

A spy has a slightly different behavior but is still comparable with a mock. Again, from the official docs, we read,

“Creates a mock function similar to jest.fn() but also tracks calls to object[methodName]. Returns a Jest mock function.”

What this means is that the function acts as it normally would—however, all calls are being tracked. This allows you to verify if a function has been called the right number of times and held the right input parameters.

Below, you’ll find an example where we want to check if the play method of a video returns the correct result but also gets called with the right parameters. We spy on the play method of the video object. Next, we call the play method and check if the spy has been called and if the returned result is correct. Pretty straightforward! In the end, we must call the mockRestore method to reset a mock to its original implementation.

const video = require('./video');

test('plays video', () => {
const spy = jest.spyOn(video, 'play');
const isPlaying = video.play();

expect(spy).toHaveBeenCalled();
expect(isPlaying).toBe(true);

spy.mockRestore();
});


Jest Basics

Let’s take a look at some basics on writing tests with Jest.

Describe Blocks

A describe block is used for organizing test cases in logical groups of tests. For example, we want to group all the tests for a specific class. We can further nest new describe blocks in an existing describe block. To continue with the example, you can add a describe block that encapsulates all the tests for a specific function of this class.

“It” or “Test“ Tests

We use the test keyword to start a new test case definition. The it keyword is an alias for the test keyword. Personally, I like to use it, which allows for more natural language flow of writing tests. For example:

describe('Beverage()', () => {
   it('should be delicious', () => {
      expect(myBeverage.delicious).toBeTruthy();
   });
});

Matchers

Next, let’s look at the matchers Jest exposes. A matcher is used for creating assertions in combination with the expect keyword. We want to compare the output of our test with a value we expect the function to return.

Again, let’s look at a simple example where we want to check if an instance of a class is the correct class we expect. We place the test value in the expect keyword and call the exposed matcher function toBeInstanceOf(<class>) to compare the values. The test results in the following code:

it('should be instance of Car', () => {
   expect(newTruck()).toBeInstanceOf(Car);
});

The complete list of exposed matchers can be found in the Jest API reference.

Snapshot Testing for React Front Ends

At last, the Jest documentation suggests using snapshot tests to detect UI changes. As I mentioned earlier, snapshot testing can also be applied for checking larger objects, or even the JSON response for API endpoints.

Let’s take a look at an example for React where we simply want to create a snapshot for a link object. The snapshot itself will be stored with the tests and should be committed alongside code changes.

it('renders correctly', () => {
   const tree = renderer
      .create(<Link page="http://www.facebook.com">Facebook</Link>)
      .toJSON();
   expect(tree).toMatchSnapshot();
});

Following, the above code renders the following snapshot:

exports[`renders correctly 1`] = `
<a
  className="normal"
  href="http://www.facebook.com"
  onMouseEnter={[Function]}
  onMouseLeave={[Function]}
>
  Facebook
</a>
`;

If the link object changes, this test will fail in the future. If the changes to the UI elements are correct, you should update the snapshots by storing the results in the snapshot file. You can automatically update snapshots using the Jest CLI tool by adding a “-u” flag when executing the tests.


Conclusion

In this article, We understood about the Jest Framework Concepts . We learnt more about the vocabulary associated with Jest testing, like mocks and spies. Also, we have covered some of the basics of Jest testing, like using describe blocks and the keywords it and expect with snapshot testing and why it’s particularly useful for front-end testing.

Thanks for reading ! I hope you enjoyed and learned about the Jest unit testing framework concepts . Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING!!???

React Native – Understanding Direct Manipulation

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will learn about Direct Manipulation in React Native. Direct manipulation is an important concept in react native.

To understand the direct manipulation concept, we will discuss the below topics :

  • What is Direct Manipulation ?
  • How Direct Manipulation Works ?
  • UseCase using setState and setNativeProps

A famous quote about learning is :

” We now accept the fact that learning is a lifelong process of keeping abreast of change. And the most pressing task is to teach people how to learn.”

So, Let’s begin.


What is Direct Manipulation ?

The definition of Direct Manipulation says that 

Direct Manipulation is the process of making a component changes directly without using state/props or render whole hierarchies of components for a small change in one component.

Before the understanding of direct manipulation, we need to understand that how any components display on the UI Screen ?

The answer is that we need to write code for that components in render() method to display any component in the screen.

Now, what if you want to add/change any component?

The answer is we have to change state or props, otherwise the render() method will not be called. The render() method renders the whole component hierarchies even if there is a change in the only one component.

So the solution for this problem is Direct Manipulation that does not render all the component hierarchies for one component change.

In other way, we can say that

It is sometimes necessary to make changes directly to a component without using state/props to trigger a re-render of the entire subtree (or render the whole hierarchies of components for a small change in one component). This process is called Direct Manipulation.


How Direct Manipulation Works ?

In this section, we will see that how to work Direct Manipulation.

Direct Manipulation uses setNativeProps and Refs. setNativeProps is the react native equivalent to setting the properties directly on a DOM node.

and then, next question is “When to use setNativeProps and Refs ?”

Use setNativeProps when frequent re-rendering creates a performance bottleneck.

Direct manipulation will not be a tool that we reach for frequently; we will typically only be using it for creating continuous animations to avoid the overhead of rendering the component hierarchy and reconciling many views. setNativeProps is imperative and stores state in the native layer (DOM, UIView, etc.) and not within our React components, which makes our code more difficult to reason about. Before we use it, try to solve our problem with setState and shouldComponentUpdate.


UseCase

Let’s understand setNativeProps /Refs and setState concepts with one use case with the below code examples:

We have one TextInput which should be cleared when button is pressed.


1. Using setState

import React from 'react';
import {
  TextInput,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';

export default class App extends React.Component {

    constructor(props) {
      super(props)
      this.state = {
        inputText: '',
      }
    }
    clearText = () => {
        this.setState({
            inputText : ''
        })
    }

    render(){
        console.log("render method is called")
        return( 
        <View style={{justifyContent :'center',flex:1}}>
            <TextInput
            style={{height: 50,marginHorizontal: 20, borderWidth: 1, borderColor: '#ccf'}}
            value = {this.state.inputText}
            onChangeText= {(text) =>{
                this.setState({
                    inputText : text
                })
            }}
            />
            <TouchableOpacity onPress={()=>this.clearText()}>
                <Text>Clear Text</Text>
            </TouchableOpacity>
        </View>
        );
    }
}

In this above code example, we change the text or clear button each time. Render method is called which re-render the whole component even if there is a change for the component.


2. Using setNativeProps

import React from 'react';
import {
  TextInput,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';

export default class App extends React.Component {

    constructor(props) {
      super(props)
      this.state = {
        text: '',
      }
    }

    clearText = () => {
      this._textInput.setNativeProps({
        text: ' '
      });
    }

    render(){
        return( 
        <View style={{justifyContent :'center',flex:1}}>
            <TextInput
            ref={component => { this._textInput = component}}
            style={{height: 40,marginHorizontal: 18, borderWidth: 1, borderColor: '#ccc'}}
            onChangeText= {(text) =>{
                this._textInput.setNativeProps({text: text});
            }}
            />

            <TouchableOpacity onPress={clearText}>
                <Text>Clear Text</Text>
            </TouchableOpacity>
        );
    }
}

In above code example, render method will not be called when we click on clear text button or text is changed.

So Here the component will not be re-rendered. We can change any props of a component using setProps and Refs without using re-render().

Some times If we update a property that is also managed by the render function, we might end up with some unpredictable and confusing bugs because anytime the component re-renders and that property changes, whatever value was previously set from setNativeProps will be completely ignored and overridden. So we need to avoid conflict with the render function.

By intelligently applying shouldComponentUpdate, we can avoid the unnecessary overhead involved in reconciling unchanged component subtrees, to the point where it may be performant enough to use setState instead of setNativeProps.

That’s all about in this article.


Conclusion

In this article, We understood about Direct Manipulation in React Native. We also discussed how Direct Manipulation works with use-case. In Summary, we can say that :

  • Direct Manipulation is the process of making a component changes directly without using state/props.
  • Direct Manipulation helps to prevent render all the component hierarchies for one component change.
  • Direct Manipulation uses setNativeProps and Refs when frequent re-rendering creates a performance bottleneck.

Thanks for reading ! I hope you enjoyed and learned about the Direct Manipulation concepts in React Native. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

React Native – How To Secure Mobile Application In React Native ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will learn how to secure Mobile application in React Native. We will discuss Security related areas and techniques to secure mobile application. React Native is a popular cross-platform JavaScript framework. Components of React Native apps are rendered in Native UI. In this article, we will focus on the security side of the framework. In this article, we will focus on the security side of the framework.

A famous quote about learning is :

” Develop a passion for learning. If you do, you will never cease to grow.”

So Let’s begin.


Analyzing React Native

React Native has an alternative approach for cross-platform development. Traditionally, Cordova-based frameworks used WebView to render the whole application. In contrast, React Native applications run the JS code in a JavaScript VM based on JavaScriptCore. The application uses native JavaScriptCore on iOS and JavaScriptCore libs are bundled on an APK on Android.

In React Native, the communication between Native and JavaScript code is handled by a JavaScript Bridge. The source JS files are compiled into one single bundle file known as entry file. In development mode, the file is bundled on a local server and fetched by the application. For production, the application logic is usually bundled in a single file, usually “index.android.bundle” or “index.ios.bundle“. 

Similarly to Cordova, the bundle file is present in the assets folder and, as also happens with Cordova, we can assume React Native apps as containers that run JS code. This logic is implemented in the expo. Under certain limitations, Expo can run different business logic in a single application. At this moment, it’s fair to assume the entry-file as the core application logic.


Major Sections of Secure Mobile Application

Secure Mobile Application is divided into three sections :

  • Securing application to server connection
  • Securing local storage
  • Advanced integrity checks


1. Securing Application to Server Connection

Usually, smartphone apps communicate with the backend server via APIs. Insecure Communication is highlighted in the OWASP Mobile Top 10 at #3:

Mobile applications frequently do not protect network traffic. They may use SSL/TLS during authentication but not elsewhere. This inconsistency leads to the risk of exposing data and session IDs to interception. The use of transport security does not mean the app has implemented it correctly. To detect basic flaws, observe the phone’s network traffic. More subtle flaws require inspecting the design of the application and the applications configuration. – M3-Insecure Communication.

Starting from iOS 9 and Android Pie, SSL is required by default. We can enable cleartext traffic but it’s not recommended. To secure the connection further, we can pin our server certificates.


SSL Pinning in React Native

Apps are dependent on Certificate Authorities (CA) and Domain Name Servers (DNS) to validate domains for TLS. Unsafe certificates can be installed on a user device, thereby opening the device to a Man-in-the-Middle attack. SSL pinning can be used to mitigate this risk.

We use the fetch API or libraries like axios or frisbee to consume APIs in our React Native applications. However, these libraries don’t have support for SSL pinning. Let’s explore the available plugins:

  • react-native-ssl-pinning: this plugin uses OkHttp3 on Android and AFNetworking on iOS to provide SSL pinning and cookie handling. In this case, we will be using fetch from the library to consume APIs. For this library, we will have to bundle the certificates inside the app. Necessary error handling needs to be implemented in older apps to handle certificate expiry. The app needs to be updated with newer certificates before certificates expire. This library uses promises and supports multi-part form data.
  • react-native-pinch: this plugin is similar to react-native-ssl-pinning. We have to bundle certificates inside the app. This library supports both promises and callbacks.

To use HPKP (Http Public Key Pinning), we can consider these plugins:

  • react-native-cert-pinner: this plugin allows us to use public hashes to pin the server. Unlike the plugins above, we can use fetch and other utilities directly. The pinning occurs before native JS is run. Also, there is no requirement to define hashes in the request itself.
  • react-native-trustkit: this is a wrapper plugin for the iOS Trustkit library. This library is available for iOS only.


2. Securing Local Storage

Normally, we store data inside our application to achieve offline functionality. There are multiple ways to store persistent data in React Native. Async-storage, sqlite, pouchdb and realm are some of the methods to store data.

Insecure storage is highlighted at #2 in the OWASP Mobile Top 10:

Insecure data storage vulnerabilities occur when development teams assume that users or malware will not have access to a mobile device’s filesystem and subsequent sensitive information in data-stores on the device. Filesystems are easily accessible. Organizations should expect a malicious user or malware to inspect sensitive data stores. Usage of poor encryption libraries is to be avoided. Rooting or jailbreaking a mobile device circumvents any encryption protections. When data is not protected properly, specialized tools are all that is needed to view application data. – M2-Insecure Data Storage.

Let’s take a look at some plugins which add a layer of security to our application. Also, we will be exploring some plugins which use native security features Keychain and Keystore Access.


SQLite

SQLite is the most common way to store data. A very popular and open-source extension for SQLite encryption is SQLCipher. Data in SQLCipher is encrypted via 256 bit AES which can’t be read without a key. React Native has two libraries that provide SQLCipher:

  • react-native-sqlcipher-2 : this is a fork of react-native-sqlite-2. We can use pouchdb as an ORM provider with this library, so it’s an additional bonus.
  • react-native-sqlcipher-storage : this is a fork of react-native-sqlite-storage. The library has to be set up manually since it doesn’t seem to support react-native link. Interestingly, the library is based on the Cordova implementation.


Realm

Realm is a nice alternative database provider to React Native Apps. It’s much faster than SQLite and it has support for encryption by default. It uses the AES256 algorithm and the encrypted realm is verified using SHA-2 HMAC hash.


Keychain and Keystore Access

Both iOS and Android have native techniques to store secure data. Keychain services allows developers to store small chunks of data in an encrypted database. On Android, most plugins use the Android keystore system for API 23(Marshmallow) and above. For lower APIs, Facebook’s conceal provides the necessary crypto functions. Another alternative is to store encrypted data in shared preferences.

React Native has three libraries that provide secure storage along with biometric/face authentication:

  • React Native KeyChain: As the name implies, this plugin provides access to keychain/keystore. It uses Keychain (iOS), Keystore (Android 23+), and conceal. There is support for Biometric Auth. This plugin has multiple methods and options for both Android and iOS. However, it only allows the storage of the username & password.
  • React Native Sensitive Info: This plugin is similar to React Native Keychain. It uses Keychain (iOS) and shared preferences (Android) to store data. We can store multiple key-value pairs using this plugin.
  • RN Secure Storage: This plugin is similar to React Native Sensitive Info. It uses Keychain (iOS), Keystore (Android 23+), and Secure Preferences to store data. We can store multiple key-value pairs.


3. Advanced Integrity Checks


JailMonkey and SafetyNet

Rooted and jailbroken devices should be considered insecure by intent. Root privileges allow users to circumvent OS security features, spoof data, analyze algorithms, and access secured storage. As a rule of thumb, the execution of the app on a rooted device should be avoided.

JailMonkey allows React Native applications to detect root or jailbreak. Apart from that, it can detect if mock locations can be set using developer tools.

SafetyNet is an Android-only API for detecting rooted devices and boot loader unlocks. 

react-native-google-safetynet is a wrapper plugin for SafetyNet’s attestation API. It can be used to verify the user’s device.

Additionally, we can use react-native-device-info to check if an app is running in an emulator.


Protecting the Application Logic

Earlier in the article, we mentioned how the application logic in entry-file is available in plain sight. In other words, a third-party can retrieve the code, reverse-engineer sensitive logic, or even tamper with the code to abuse the app (such as unlocking features or violating license agreements).

Protecting the application logic is a recommendation in the OWASP Mobile Top 10. Specifically, the main concerns include code tampering:

Mobile code runs within an environment that is not under the control of the organization producing the code. At the same time, there are plenty of different ways of altering the environment in which that code runs. These changes allow an adversary to tinker with the code and modify it at will. — M8-Code Tampering. “

And reverse engineering:

Generally, most applications are susceptible to reverse engineering due to the inherent nature of code. Most languages used to write apps today are rich in metadata that greatly aides a programmer in debugging the app. This same capability also greatly aides an attacker in understanding how the app works. — M9-Reverse Engineering.”

Let’s highlight two different strategies to address this risk.


Hermes

Facebook introduced Hermes with the react-native 0.60.1 release. Hermes is a new JavaScript Engine optimized for mobile apps. Currently, it is only available with Android and it’s usage is optional. Hermes can be used in the project with react-native 0.60.4 by changing the enableHermes flag in build.gradle file.

Its key benefits are improved start-up time, decreased memory usage, and smaller app size. One of the strategies that Hermes uses to achieve this is precompiling JavaScript to bytecode.

Let’s look at a real example. We assume that our entry-file is the one found below:

const {createDecipheriv, createCipheriv, randomBytes} = require('crypto');
const key = Buffer.from('60adba1cf391d89a3a71c72a615cbba8', 'hex');
const algorithm = 'aes-128-cbc';
const softwareVersion = '2.0';
module.exports.createKey = function(userId, expireDate) {
  const payload = {
    userId,
    expireDate,
    softwareVersion
  };
  const json = Buffer.from(JSON.stringify(payload), 'utf8');
  const iv = randomBytes(16);
  const cipher = createCipheriv(algorithm, key, iv);
  let encoded = cipher.update(json);
  encoded = Buffer.concat([encoded, cipher.final()]);
  const joined = iv.toString('hex') + ';' + encoded.toString('hex');
  return Buffer.from(joined, 'utf8').toString('base64');
}
module.exports.validateLicense = function(license, userId) {
  const licenseFields = Buffer.from(license, 'base64').toString('utf8');
  const fields = licenseFields.split(';');
  const iv = Buffer.from(fields[0], 'hex');
  const data = Buffer.from(fields[1], 'hex');
  const decipher = createDecipheriv(algorithm, key, iv);
  let decoded = decipher.update(data);
  decoded = Buffer.concat([decoded, decipher.final()]);
  const result = JSON.parse(decoded);
  if (result.userId != userId) {
    throw new Error('Wrong user');
  }
  if (new Date(result.expireDate) < new Date()) {
    throw new Error('Expired license');
  }
  if (result.softwareVersion != softwareVersion) {
    throw new Error('This license is not valid for this program version');
  }
  return result;
}

After Hermes compiles this file, the resulting bytecode can easily be decompiled using hbcdump and, among the decompiled code, we find some easy to read code look like:

s0[ASCII, 0..-1]: 
s1[ASCII, 0..2]: 2.0
s2[ASCII, 3..34]: 60adba1cf391d89a3a71c72a615cbba8
s3[ASCII, 35..35]: ;
s4[ASCII, 36..50]: Expired license
s5[ASCII, 71..120]: This license is not valid for this program version
s6[ASCII, 121..130]: Wrong user
s7[ASCII, 133..143]: aes-128-cbc
s8[ASCII, 143..148]: crypto
s9[ASCII, 154..159]: global
s10[ASCII, 160..165]: base64
s11[ASCII, 166..168]: hex
s12[ASCII, 177..180]: utf8
i13[ASCII, 50..56] #C765D706: exports
i14[ASCII, 56..70] #FF849242: softwareVersion
i15[ASCII, 127..132] #6FE51CD4: userId
i16[ASCII, 147..154] #1E019520: toString
i17[ASCII, 167..176] #68A06D42: expireDate
i18[ASCII, 173..176] #CD347266: Date
i19[ASCII, 181..186] #5AA7C487: Buffer
i20[ASCII, 186..196] #FD81EB01: randomBytes
i21[ASCII, 196..200] #0EC469F8: split
i22[ASCII, 201..205] #9102A3D0: Error
i23[ASCII, 205..211] #EB75CA32: require
i24[ASCII, 212..215] #971CE5C7: JSON
i25[ASCII, 216..221] #CB8DFA65: concat
i26[ASCII, 222..235] #96C7181F: createCipheriv
i27[ASCII, 235..249] #D60B6B51: validateLicense
i28[ASCII, 250..265] #723D6A80: createDecipheriv
i29[ASCII, 266..274] #01D3AE7D: createKey
i30[ASCII, 275..279] #47993A63: final
i31[ASCII, 280..283] #EAF03666: from
i32[ASCII, 283..288] #2A322C6E: module
i33[ASCII, 289..293] #958EDB02: parse
i34[ASCII, 294..302] #807C5F3D: prototype
i35[ASCII, 303..311] #8D1543BD: stringify
i36[ASCII, 312..317] #60396F4B: update

Function<global>0(1 params, 15 registers, 4 symbols):
Offset in debug table: src 0x0, vars 0x0
license.js[1:1]
    CreateEnvironment r0
    GetGlobalObject   r1
    TryGetById        r4, r1, 1, "require"
    LoadConstUndefined r3
    LoadConstString   r2, "crypto"
    Call2             r2, r4, r3, r2
    GetByIdShort      r3, r2, 2, "createDecipheriv"
    StoreToEnvironment r0, 0, r3
    GetByIdShort      r3, r2, 3, "createCipheriv"
    StoreToEnvironment r0, 1, r3
    GetByIdShort      r2, r2, 4, "randomBytes"
    StoreToEnvironment r0, 2, r2
    TryGetById        r5, r1, 5, "Buffer"
    GetByIdShort      r4, r5, 6, "from"
    LoadConstString   r3, "60adba1cf391d89a3"...
    LoadConstString   r2, "hex"
    Call3             r2, r4, r5, r3, r2
    StoreToEnvironment r0, 3, r2
    TryGetById        r2, r1, 7, "module"
    GetByIdShort      r3, r2, 8, "exports"
    CreateClosure     r2, r0, 1
    PutById           r3, r2, 1, "createKey"
    TryGetById        r1, r1, 7, "module"
    GetByIdShort      r1, r1, 8, "exports"
    CreateClosure     r0, r0, 2
    PutById           r1, r0, 2, "validateLicense"
    Ret               r0

So, while Hermes introduces a certain degree of complexity to the entry-file code, it doesn’t actually conceal the code nor do anything to prevent code tampering, which means that it won’t stop an attacker ⁠— let’s not forget that this is not even the purpose of Hermes.

And this leads us to an approach that obfuscates React Native’s JavaScript source code to effectively mitigate the risk of code tampering and reverse engineering: Jscrambler.


Jscrambler

Jscrambler provides a series of layers to protect JavaScript. Unlike most tools that only include (basic) obfuscation, Jscrambler provides three security layers:

  • Polymorphic JavaScript & HTML5 obfuscation
  • Code locks (domain, OS, browser, time frame)
  • Self-defending (anti-tampering & anti-debugging)

By protecting the source code of React Native apps with Jscrambler, the resulting code is highly obfuscated, as can be observed below:

On top of this obfuscation, there’s a Self-Defending layer that provides anti-debugging and anti-tampering capabilities and enables setting countermeasures like breaking the application, deleting cookies, or destroying the attacker’s environment.

That’s all about in this article.


Conclusion

In this article, We learned how to secure Mobile applications in React Native. We discussed about Mobile application security related areas and techniques for React Native . It provides an overview of techniques to help to secure the React Native application. It’s then crucial to create a threat model , and depending on the application’s use case, employ the required measures to ensure that the application is properly secured.

Thanks for reading ! I hope you enjoyed and learned about the Mobile Application Security concepts in React Native. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

Exit mobile version