Android – 5 Quick Valuable Concepts To Learn Kotlin Programming Language

Hello Readers, CoolMonkTechie heartily welcomes you in this article (5 Quick Valuable Concepts To Learn Kotlin Programming Language).

In this article, We will learn about Valuable Concepts To Learn Kotlin Programming Language. At Google I/O 2019, Google announced that Android development will be increasingly Kotlin-first, and we’ve stood by that commitment. Kotlin is an expressive and concise programming language that reduces common code errors and easily integrates into existing apps. If we’re looking to build an Android app, we recommend starting with Kotlin to take advantage of its best-in-class features. This article shows the kotlin fundamental for android application development

For understanding the basic fundamental concepts of kotlin, we will explore the below topics one by one:

  • Variable declaration
  • Conditionals
  • Functions
  • Classes
  • Interoperability

A famous quote about learning is :

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

So Let’s begin.


1. Variable declaration

Kotlin uses two different keywords to declare variables: val and var.

  • Use val for a variable whose value never changes. We can’t reassign a value to a variable that was declared using val.
  • Use var for a variable whose value can change.

In the example below, count is a variable of type Int that is assigned an initial value of 10:

var count: Int = 10

Int is a type that represents an integer, one of the many numerical types that can be represented in Kotlin. Similar to other languages, we can also use ByteShortLongFloat, and Double depending on our numerical data.

The var keyword means that we can reassign values to count as needed. For example, we can change the value of count from 10 to 15:

var count: Int = 10
count = 15

Some values are not meant to be changed, though. Consider a String called languageName. If we want to ensure that languageName always holds a value of “Kotlin”, then we can declare languageName using the val keyword:

val languageName: String = "Kotlin"

These keywords allow us to be explicit about what can be changed. Use them to our advantage as needed. If a variable reference must be reassignable, then declare it as a var. Otherwise, use val.


Type inference

Continuing the previous example, when we assign an initial value to languageName, the Kotlin compiler can infer the type based off of the type of the assigned value.

Since the value of "Kotlin" is of type String, the compiler infers that languageName is also a String. Note that Kotlin is a statically-typed language. This means that the type is resolved at compile time and never changes.

In the following example, languageName is inferred as a String, so we can’t call any functions that aren’t part of the String class:

val languageName = "Kotlin"
val upperCaseName = languageName.toUpperCase()

// Fails to compile
languageName.inc()

toUpperCase() is a function that can only be called on variables of type String. Because the Kotlin compiler has inferred languageName as a String, we can safely call toUpperCase()inc(), however, is an Int operator function, so it can’t be called on a String. Kotlin’s approach to type inference gives us both conciseness and type-safety.


Null safety

In some languages, a reference type variable can be declared without providing an initial explicit value. In these cases, the variables usually contain a null value. Kotlin variables can’t hold null values by default. This means that the following snippet is invalid:

// Fails to compile
val languageName: String = null

For a variable to hold a null value, it must be of a nullable type. We can specify a variable as being nullable by suffixing its type with ?, as shown in the following example:

val languageName: String? = null

With a String? type, we can assign either a String value or null to languageName.

We must handle nullable variables carefully or risk a dreaded NullPointerException. In Java, for example, if we attempt to invoke a method on a null value, our program crashes.

Kotlin provides a number of mechanisms for safely working with nullable variables.


2. Conditionals

Kotlin features several mechanisms for implementing conditional logic. The most common of these is an if-else statement. If an expression wrapped in parentheses next to an if keyword evaluates to true, then code within that branch (i.e. the immediately-following code that is wrapped in curly braces) is executed. Otherwise, the code within the else branch is executed.

Example : if / else

if (count == 42) {
    println("I have the answer.")
} else {
    println("The answer eludes me.")
}

We can represent multiple conditions using else if. This lets us represent more granular, complex logic within a single conditional statement, as shown in the following example:

if (count == 42) {
    println("I have the answer.")
} else if (count > 35) {
    println("The answer is close.")
} else {
    println("The answer eludes me.")
}

Conditional Expressions

Conditional statements are useful for representing stateful logic, but we may find that we repeat ourself when writing them. In the example above, we simply print a String in each branch. To avoid this repetition, Kotlin offers conditional expressions. The last example can be rewritten as follows:

val answerString: String = if (count == 42) {
    "I have the answer."
} else if (count > 35) {
    "The answer is close."
} else {
    "The answer eludes me."
}

println(answerString)

Implicitly, each conditional branch returns the result of the expression on its final line, so we don’t need to use a return keyword. Because the result of all three branches is of type String, the result of the if-else expression is also of type String. In this example, answerString is assigned an initial value from the result of the if-else expression. Type inference can be used to omit the explicit type declaration for answerString, but it’s often a good idea to include it for clarity.

We aware that Kotlin does not include a traditional ternary operator, instead favoring the use of conditional expressions.

As the complexity of our conditional statement grows, we might consider replacing our if-else expression with a when expression, as shown in the following example:

val answerString = when {
    count == 42 -> "I have the answer."
    count > 35 -> "The answer is close."
    else -> "The answer eludes me."
}

println(answerString)

Each branch in a when expression is represented by a condition, an arrow (->), and a result. If the condition on the left-hand side of the arrow evaluates to true, then the result of the expression on the right-hand side is returned. Note that execution does not fall through from one branch to the next. The code in the when expression example is functionally-equivalent to that in the previous example but is arguably easier to read.

Smart Casting

Kotlin’s conditionals highlight one of its more powerful features, smart casting. Rather than using the safe-call operator or the not-null assertion operator to work with nullable values, we can instead check if a variable contains a reference to a null value using a conditional statement, as shown in the following example:

val languageName: String? = null
if (languageName != null) {
    // No need to write languageName?.toUpperCase()
    println(languageName.toUpperCase())
}

Within the conditional branch, languageName may be treated as non-nullable. Kotlin is smart enough to recognize that the condition for executing the branch is that languageName does not hold a null value, so we do not have to treat languageName as nullable within that branch. This smart casting works for null checkstype checks, or any condition that satisfies a contract.


3. Functions

We can group one or more expressions into a function. Rather than repeating the same series of expressions each time that we need a result, we can wrap the expressions in a function and call that function instead.

To declare a function, use the fun keyword followed by the function name. Next, define the types of inputs that our function takes, if any, and declare the type of output that it returns. A function’s body is where we define expressions that are called when our function is invoked.

Building on previous examples, here’s a complete Kotlin function:

fun generateAnswerString(): String {
    val answerString = if (count == 42) {
        "I have the answer."
    } else {
        "The answer eludes me"
    }

    return answerString
}

The function in the example above has the name generateAnswerString. It doesn’t take any input. It outputs a result of type String. To call a function, use its name, followed by the invocation operator (()). In the example below, the answerString variable is initialized with the result from generateAnswerString().

val answerString = generateAnswerString()

Functions can take arguments as input, as shown in the following example:

fun generateAnswerString(countThreshold: Int): String {
    val answerString = if (count > countThreshold) {
        "I have the answer."
    } else {
        "The answer eludes me."
    }

    return answerString
}

When declaring a function, we can specify any number of arguments and their types. In the example above, generateAnswerString() takes one argument named countThreshold of type Int. Within the function, we can refer to the argument by using its name.

When calling this function, we must include an argument within the function call’s parentheses:

val answerString = generateAnswerString(42)


Simplifying function declarations

generateAnswerString() is a fairly simple function. The function declares a variable and then immediately returns. When the result of a single expression is returned from a function, we can skip declaring a local variable by directly returning the result of the if-else expression contained in the function, as shown in the following example:

fun generateAnswerString(countThreshold: Int): String {
    return if (count > countThreshold) {
        "I have the answer."
    } else {
        "The answer eludes me."
    }
}

We can also replace the return keyword with the assignment operator:

fun generateAnswerString(countThreshold: Int): String = if (count > countThreshold) {
        "I have the answer"
    } else {
        "The answer eludes me"
    }


Anonymous functions

Not every function needs a name. Some functions are more directly identified by their inputs and outputs. These functions are called anonymous functions. We can keep a reference to an anonymous function, using this reference to call the anonymous function later. We can also pass the reference around our application, as with other reference types.

val stringLengthFunc: (String) -> Int = { input ->
    input.length
}

Like named functions, anonymous functions can contain any number of expressions. The returned value of the function is the result of the final expression.

In the example above, stringLengthFunc contains a reference to an anonymous function that takes a String as input and returns the length of the input String as output of type Int. For that reason, the function’s type is denoted as (String) -> Int. This code does not invoke the function, however. To retrieve the result of the function, we must invoke it with like we would a named function. We must supply a String when calling stringLengthFunc, as shown in the following example:

val stringLengthFunc: (String) -> Int = { input ->
    input.length
}

val stringLength: Int = stringLengthFunc("Android")


Higher-order functions

A function can take another function as an argument. Functions that use other functions as arguments are called Higher-order functions. This pattern is useful for communicating between components in the same way that we might use a callback interface in Java.

Here’s an example of a higher-order function:

fun stringMapper(str: String, mapper: (String) -> Int): Int {
    // Invoke function
    return mapper(str)
}

The stringMapper() function takes a String along with a function that derives an Int value from a String that we pass into it.

We can call stringMapper() by passing a String and a function that satisfies the other input parameter, namely a function that takes a String as input and outputs an Int, as shown in the following example:

stringMapper("Android", { input ->
    input.length
})

If the anonymous function is the last parameter defined on a function, we can pass it outside of the parentheses used to invoke the function, as shown in the following example:

stringMapper("Android") { input ->
    input.length
}

Anonymous functions can be found throughout the Kotlin standard library. 


4. Classes

All of the types mentioned so far are built into the Kotlin programming language. If we would like to add our own custom type, we can define a class using the class keyword, as shown in the following example:

class Car


Properties

Classes represent state using properties. A property is a class-level variable that can include a getter, a setter, and a backing field.

Since a car needs wheels to drive, we can add a list of Wheel objects as a property of Car, as shown in the following example:

class Car {
    val wheels = listOf<Wheel>()
}

Note that wheels is a public val, meaning that wheels can be accessed from outside of the Car class, and it can’t be reassigned. If we want to obtain an instance of Car, we must first call its constructor. From there, we can access any of its accessible properties.

val car = Car() // construct a Car
val wheels = car.wheels // retrieve the wheels value from the Car

If we want to customize our wheels, we can define a custom constructor that specifies how our class properties are initialized:

class Car(val wheels: List<Wheel>)

In the example above, the class constructor takes a List<Wheel> as a constructor argument and uses that argument to initialize its wheels property.


Class functions and encapsulation

Classes use functions to model behavior. Functions can modify state, helping us to expose only the data that we wish to expose. This access control is part of a larger object-oriented concept known as encapsulation.

In the following example, the doorLock property is kept private from anything outside of the Car class. To unlock the car, we must call the unlockDoor() function passing in a valid key, as shown in the following example:

class Car(val wheels: List<Wheel>) {

    private val doorLock: DoorLock = ...

    fun unlockDoor(key: Key): Boolean {
        // Return true if key is valid for door lock, false otherwise
    }
}

If we would like to customize how a property is referenced, we can provide a custom getter and setter. For example, if we would like to expose a property’s getter while restricting access to its setter, we can designate that setter as private:

class Car(val wheels: List<Wheel>) {

    private val doorLock: DoorLock = ...

    var gallonsOfFuelInTank: Int = 15
        private set

    fun unlockDoor(key: Key): Boolean {
        // Return true if key is valid for door lock, false otherwise
    }
}

With a combination of properties and functions, we can create classes that model all types of objects.


5. Interoperability

One of Kotlin’s most important features is its fluid interoperability with Java. Because Kotlin code compiles down to JVM bytecode, our Kotlin code can call directly into Java code and vice-versa. This means that we can leverage existing Java libraries directly from Kotlin. Furthermore, the majority of Android APIs are written in Java, and we can call them directly from Kotlin.

That’s all about in this article.


Conclusion

In this article, We understood about Valuable Concepts To Learn Kotlin Programming Language. Kotlin is a flexible, pragmatic language with growing support and momentum. We discussed about Kotlin fundamental like variable declaration, function, conditions and classes concepts which is widely used by Android developers everywhere for application development. This article showed the basic Kotlin fundamental concepts for android application development

Thanks for reading ! I hope you enjoyed and learned about the basic fundamental concepts of Kotlin for android development. 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 Android 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 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!!???

iOS – How To Respond To The Application Launch In iOS ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (How To Respond To The Application Launch In iOS ?).

In this article, We will learn how to respond to the application launch in iOS. We will discuss about initialize our app’s data structures, prepare our app to run, and respond to any launch-time requests from the system in iOS. We also describe why the app launched in iOS.

A famous quote about learning is :

” Research shows that you begin learning in the womb and go right on learning until the moment you pass on. Your brain has a capacity for learning that is virtually limitless, which makes every human a potential genius. “

So Let’s begin.


Overview

The system launches our app when the user taps our app’s icon on the Home screen. If our app requested specific events, the system might also launch our app in the background to handle those events. For a scene-based app, the system similarly launches the app when one of our scenes needs to appear onscreen or do some work.

All apps have an associated process, which the UIApplication object represents. Apps also have an app delegate object—an object that conforms to the UIApplicationDelegate protocol—which responds to important events happening within that process. Even a scene-based app uses an app delegate to manage fundamental events like launch and termination. At launch time, UIKit automatically creates the UIApplication object and our app delegate. It then starts our app’s main event loop.


Provide a Launch Storyboard

When the user first launches the app on a device, the system displays the launch storyboard until the app is ready to display its UI. Displaying the launch storyboard assures the user that our app launched and is doing something. If our app initializes itself and readies its UI quickly, the user may see the launch storyboard only briefly.

Xcode projects automatically include a default launch storyboard for us to customize, and we can add more launch storyboards as necessary. To add new launch storyboards to our project, do the following:

  1. Open your project in Xcode.
  2. Choose File > New > File.
  3. Add a Launch Screen resource to our project.

Add views to our launch storyboard and use Auto Layout constraints to size and position them so that they adapt to the underlying environment. UIKit displays exactly what we provide, using our constraints to fit our views into the available space. We can use  Human Interface Guidelines for for design guidance.

In iOS 13 and later, always provide a launch storyboard for your app. Don’t use static launch images.


Initialize App’s Data Structures

We put our app’s launch-time initialization code in one or both of the following methods:

  • application(_:willFinishLaunchingWithOptions:)
  • application(_:didFinishLaunchingWithOptions:)

UIKit calls these methods at the beginning of our app’s launch cycle. We use them to:

  • Initialize our app’s data structures.
  • Verify that our app has the resources it needs to run.
  • Perform any one-time setup when our app launches for the first time. For example, install templates or user-modifiable files in a writable directory.
  • Connect to any critical services that our app uses. For example, connect to the Apple Push Notification service if our app supports remote notifications.
  • Check the launch options dictionary for information about why our app launched.

For apps that aren’t scene-based, UIKit loads our default user interface automatically at launch time. Use the application(_:didFinishLaunchingWithOptions:) method to make additional changes to that interface before it appears onscreen. For example, we might install a different view controller to reflect what the user was doing the last time they used the app.


Move Long-Running Tasks off the Main Thread

When the user launches the app, make a good impression by launching quickly. UIKit doesn’t present the app’s interface until after the application(_:didFinishLaunchingWithOptions:) method returns. Performing long-running tasks in that method or the application(_:willFinishLaunchingWithOptions:) method might make the app appear sluggish to the user. Returning quickly is also important when launching to the background because the system limits the app’s background execution time.

Move tasks that are not critical to the app’s initialization out of the launch-time sequence. For example:

  • Defer the initialization of features that the app doesn’t need immediately.
  • Move important, long-running tasks off the app’s main thread. For example, run them asynchronously on a global dispatch queue.


Determine Why App Launched

When UIKit launches the app, it passes along a launch options dictionary to the application(_:willFinishLaunchingWithOptions:) and application(_:didFinishLaunchingWithOptions:) methods with information about why the app launched. The keys in that dictionary indicate important tasks to perform immediately. For example, they might reflect actions that the user started elsewhere and wants to continue in the app. Always check the contents of the launch options dictionary for keys that we expect, and respond appropriately to their presence.

For a scene-based app, examine the options that UIKit passes to the application(_:configurationForConnecting:options:) method to determine why it created the scene.

The example shows the app delegate method for an app that handles background location updates. When the location key is present, the app starts location updates immediately instead of deferring them until later. Starting location updates allows the Core Location framework to deliver the new location event.

class AppDelegate: UIResponder, UIApplicationDelegate, 
               CLLocationManagerDelegate {
    
   let locationManager = CLLocationManager()
   func application(_ application: UIApplication,
              didFinishLaunchingWithOptions launchOptions:
              [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
       
      // If launched because of new location data,
      //  start the visits service right away.
      if let keys = launchOptions?.keys {
         if keys.contains(.location) {
            locationManager.delegate = self
            locationManager.startMonitoringVisits()
         }
      }
       
      return true
   }
   // other methods…
}

The system doesn’t include a key unless our app supports the corresponding feature. For example, the system doesn’t include the remoteNotification key for an app that doesn’t support remote notifications.

That’s all about in this article.


Conclusion

In this article, We understood how to respond to the application launch in iOS. This article described about initialize our app’s data structures, prepare our app to run, and respond to any launch-time requests from the system in iOS.

Thanks for reading ! I hope you enjoyed and learned about the Application Launch Concepts in iOS. 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 other website and tutorials of iOS 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 Implement Animations Using The Animated API In React Native ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (How To Implement Animations Using The Animated API In React Native ?).

In this article, We will learn how to implement animations using the animated api in react native platform. Animation is an important part of user experience design. It serves as feedback on user actions, informs users of system status, and guides them on how to interact with the interface.  This article demonstrates the practical implementation of Animations in React native application. The recommended way to animate in React Native for most cases is by using the Animated API.

A famous quote about learning is :

” He who laughs most, learns best. “


So Let’s begin.


Animation Methods

There are three main Animated methods that we can use to create animations:

  1. Animated.timing() — Maps time range to easing value.
  2. Animated.decay() — starts with an initial velocity and gradually slows to a stop.
  3. Animated.spring() — Simple single-spring physics model (Based on Rebound and Origami). Tracks velocity state to create fluid motions as the toValue updates, and can be chained together.

Along with these three Animated methods, there are three ways to call these animations along with calling them individually. We will be covering all three of these as well:

  1. Animated.parallel() — Starts an array of animations all at the same time.
  2. Animated.sequence() — Starts an array of animations in order, waiting for each to complete before starting the next. If the current running animation is stopped, no following animations will be started.
  3. Animated.stagger() — Array of animations may run in parallel (overlap), but are started in sequence with successive delays. Very similar to Animated.parallel() but allows us to add delays to the animations.


1. Animated.timing()


1.1 Animated.timing Basic Example

The first animation we will be creating is this spinning animation using Animated.timing().

// Example implementation:
Animated.timing(
  someValue,
  {
    toValue: number,
    duration: number,
    easing: easingFunction,
    delay: number
  }
)

This type of infinite animation can be useful to use when creating loading indicators, and is one of the more useful animations that we’ve used in many of React Native projects. This concept can also be used to create infinite animations of other types such as scaling up and down or some other type to indicate loading.

To get started, we need to either start with a new React Native project or with a blank existing React Native project. To get started with a new project, type react-native init and the name of the project in the folder in which we will be working in and then cd into that directory:

react-native init animations
cd animations

Now that we are in this folder, open the index.js  file. Now that we have a new project created, the first thing we will need to do is import AnimatedImage, and Easing from react-native below View that is already being imported:

import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Animated,
  Image,
  Easing
} from 'react-native'

Animated is the library we will be using to create the animations, and ships with React Native.

Image is needed so we can create an image in our UI.

Easing is a module that also ships with React Native. It allows us to use various predefined easing methods such as lineareasequadcubicsinelasticbouncebackbezierinoutinout, and others. We will be using linear as to have a consistent linear motion. We will have a better idea of how to implement them after this section is finished.

Next, we need to set an initial animated value for our spinning value. To do this, we will set the value in our constructor:

constructor () {
  super()
  this.spinValue = new Animated.Value(0)
}

We declare spinValue as a new Animated.Value and pass in 0 (zero). Next, we need to create a spin method and call this method on componentDidMount to get it going when the app loads:

componentDidMount () {
  this.spin()
}
spin () {
  this.spinValue.setValue(0)
  Animated.timing(
    this.spinValue,
    {
      toValue: 1,
      duration: 4000,
      easing: Easing.linear
    }
  ).start(() => this.spin())
}

Here, this spin() method does the following steps:

  1. Sets this.spinValue back to zero
  2. Calls the Animated.timing method and animates this.spinValue to a value of 1 with a duration of 4000 milliseconds and an easing of Easing.linearAnimated.timing takes two arguments, a value (this.spinValue) and a config object. This config object can take a toValue, a duration, an easing method, and a delay.
  3. We call start() on this Animated.timing method, and pass in a callback of this.spin which will be called when the animation is completed, basically creating an infinite animation. start() takes a completion callback that will be called when the animation is done. If the animation is done because it finished running normally, the completion callback will be invoked with {finished: true}, but if the animation is done because stop was called on it before it could finish (e.g. because it was interrupted by a gesture or another animation), then it will receive {finished: false}.

Now that our methods are set up, we need to render the animation in our UI. To do so, we need to update our render method:

render () {
  const spin = this.spinValue.interpolate({
    inputRange: [0, 1],
    outputRange: ['0deg', '360deg']
  })
  return (
    <View style={styles.container}>
      <Animated.Image
        style={{
          width: 227,
          height: 200,
          transform: [{rotate: spin}] }}
          source={{uri: 'https://s3.amazonaws.com/media-p.slid.es/uploads/images/1198519/reactjs.png'}}
      />
    </View>
  )
}

Here, the render() method does the following steps:

  1. We create a variable named spin. In this variable we call interpolate() on this.spinValueinterpolate() is a method that is available to be called on any Animated.Value. interpolate is a method that interpolates the value before updating the property, e.g. mapping 0–1 to 0–10. So in our example, we need to map 0 (zero) degrees to 360 degrees numerically, using the numbers zero to one, and this method easily allows us to do this. We pass in an inputRange and outputRange array, and pass in [0,1] as the inputRange and [‘0deg’, ‘360deg’] as the outputRange.
  2. We return a View with a style of container, and an Animated.Image (React logo) with a heightwidth, and a transform property in which we attach our spin value to the rotate property, which is where the animation takes place:
transform: [{rotate: spin}]

Finally, we have the container style to center everything:

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

That’s it, the animation should be working now!

The final code for this animation with a working example is :

index.js

import React, { Component } from 'react'
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Animated,
  Image,
  Easing
} from 'react-native'

const timing = 4000

class animations extends Component {
  constructor () {
    super()
    this.spinValue = new Animated.Value(0)
  }
  componentDidMount () {
    this.spin()
  }
  spin () {
    this.spinValue.setValue(0)
    Animated.timing(
      this.spinValue,
      {
        toValue: 1,
        duration: timing,
        easing: Easing.linear
      }
    ).start(() => this.spin())
  }
  render () {
    /* This also works, to show functions instead of strings */
    // const getStartValue = () => '0deg'
    // const getEndValue = () => '360deg'
    // const spin = this.spinValue.interpolate({
    //   inputRange: [0, 1],
    //   outputRange: [getStartValue(), getEndValue()]
    // })
    const spin = this.spinValue.interpolate({
      inputRange: [0, 1],
      outputRange: ['0deg', '360deg']
    })
    return (
      <View style={styles.container}>
        <Animated.Image
          style={{ width: 227, height: 200, transform: [{rotate: spin}] }}
          source={{uri: 'https://s3.amazonaws.com/media-p.slid.es/uploads/images/1198519/reactjs.png'}}/>
      </View>
    )
  }
}

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

AppRegistry.registerComponent('animations', () => animations)

Note that – Use own image url for example code testing.

The output of the above example is :


1.2 Animated.timing multiple animation Example

Now that we know the basics of Animated.timing, let’s take a look at a few more examples of how to use Animated.timing along with interpolate and declare some other animations.

In the next example, we will declare a single animation value, this.animatedValue, and use the single animated value along with interpolate to create multiple animations, animating the following style properties:

  1. marginLeft
  2. opacity
  3. fontSize
  4. rotateX

To get started, either begin with a new branch or clear out our old code from the last project.

The first thing we will do is create the animated value that we will be using for these animations in the constructor:

constructor () {
  super()
  this.animatedValue = new Animated.Value(0)
}

Next, we create the animate method and call it in componentDidMount() :

componentDidMount () {
  this.animate()
}
animate () {
  this.animatedValue.setValue(0)
  Animated.timing(
    this.animatedValue,
    {
      toValue: 1,
      duration: 2000,
      easing: Easing.linear
    }
  ).start(() => this.animate())
}

In the render method, we create 5 different interpolated value variables:

render () { 
  const marginLeft = this.animatedValue.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 300]
  })
  const opacity = this.animatedValue.interpolate({
    inputRange: [0, 0.5, 1],
    outputRange: [0, 1, 0]
  })
  const movingMargin = this.animatedValue.interpolate({
    inputRange: [0, 0.5, 1],
    outputRange: [0, 300, 0]
  })
  const textSize = this.animatedValue.interpolate({
    inputRange: [0, 0.5, 1],
    outputRange: [18, 32, 18]
  })
  const rotateX = this.animatedValue.interpolate({
    inputRange: [0, 0.5, 1],
    outputRange: ['0deg', '180deg', '0deg']
  })
...
}

interpolate is a very powerful method, allowing us to use this.animatedValue , a single animated value, in many ways. Because the value simply changes from zero to one, we are able to interpolate this property for styling opacity, margins, text sizes, and rotation properties.

We then return Animated.View and Animated.Text components implementing these new variables:

return (
    <View style={styles.container}>
      <Animated.View
        style={{
          marginLeft,
          height: 30,
          width: 40,
          backgroundColor: 'red'}} />
      <Animated.View
        style={{
          opacity,
          marginTop: 10,
          height: 30,
          width: 40,
          backgroundColor: 'blue'}} />
      <Animated.View
        style={{
          marginLeft: movingMargin,
          marginTop: 10,
          height: 30,
          width: 40,
          backgroundColor: 'orange'}} />
      <Animated.Text
        style={{
          fontSize: textSize,
          marginTop: 10,
          color: 'green'}} >
          Animated Text!
      </Animated.Text>
      <Animated.View
        style={{
          transform: [{rotateX}],
          marginTop: 50,
          height: 30,
          width: 40,
          backgroundColor: 'black'}}>
        <Text style={{color: 'white'}}>Hello from TransformX</Text>
      </Animated.View>
    </View>
)

We also update our container styling:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 150
  }
})

That’s it, the animation should be working now!

The final code for this animation with a working example is :

index.js

import React, { Component } from 'react'
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Animated,
  Image,
  Easing
} from 'react-native'

class animations extends Component {
  constructor () {
    super()
    this.animatedValue = new Animated.Value(0)
  }
  componentDidMount () {
    this.animate()
  }
  animate () {
    this.animatedValue.setValue(0)
    Animated.timing(
      this.animatedValue,
      {
        toValue: 1,
        duration: 2000,
        easing: Easing.linear
      }
    ).start(() => this.animate())
  }
  render () {
    const marginLeft = this.animatedValue.interpolate({
      inputRange: [0, 1],
      outputRange: [0, 300]
    })
    const opacity = this.animatedValue.interpolate({
      inputRange: [0, 0.5, 1],
      outputRange: [0, 1, 0]
    })
    const movingMargin = this.animatedValue.interpolate({
      inputRange: [0, 0.5, 1],
      outputRange: [0, 300, 0]
    })
    const textSize = this.animatedValue.interpolate({
      inputRange: [0, 0.5, 1],
      outputRange: [18, 32, 18]
    })
    const rotateX = this.animatedValue.interpolate({
      inputRange: [0, 0.5, 1],
      outputRange: ['0deg', '180deg', '0deg']
    })
    return (
      <View style={styles.container}>
        <Animated.View
          style={{
            marginLeft,
            height: 30,
            width: 40,
            backgroundColor: 'red'}} />
        <Animated.View
          style={{
            opacity,
            marginTop: 10,
            height: 30,
            width: 40,
            backgroundColor: 'blue'}} />
        <Animated.View
          style={{
            marginLeft: movingMargin,
            marginTop: 10,
            height: 30,
            width: 40,
            backgroundColor: 'orange'}} />
        <Animated.Text
          style={{
            fontSize: textSize,
            marginTop: 10,
            color: 'green'}} >
            Animated Text!
        </Animated.Text>
        <Animated.View
          style={{
            transform: [{rotateX}],
            marginTop: 50,
            height: 30,
            width: 40,
            backgroundColor: 'black'}}>
          <Text style={{color: 'white'}}>Hello from TransformX</Text>
        </Animated.View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 150
  }
})

AppRegistry.registerComponent('animations', () => animations)

The output of the above example is :


2. Animated.decay()

Decay used to animate the value from its initial velocity down to zero using the deceleration option.

state = {
  animation: new Animated.Value(-150)
}

componentDidMount() {
  Animated.decay(
    this.state.animation,
    {
      toValue: 200,
      duration: 2000,
      velocity: 0.95,
      deceleration: 0.998 // By default equals to 0.997
    }
  ).start();
}

To demonstrate that we are going to use Motion example. In this example, we are moving the box down the screen. Once the box reaches the finishing line at 200 points below the center, the decay effect applies. The box keeps moving, but its speed is slowing down until it stops.

The final code for this animation with a working example is :

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

export default class App extends React.Component {
  state = {
    animation: new Animated.Value(-150)
  }

  componentDidMount() {
    Animated.decay(
      this.state.animation,
      {
        toValue: 200,
        duration: 2000,
        velocity: 0.95,
        deceleration: 0.998
      }
    ).start();
  }

  render() {
    const animationStyles = {
      transform: [
        { translateY: this.state.animation }
      ]
    };

    return (
      <Animated.View style={[objectStyles.object, animationStyles]}>
      </Animated.View>
    );
  }
}

const objectStyles = {
  object: {
    backgroundColor: 'orange',
    width: 100,
    height: 100
  }
}

The output of the above example is :


3. Animated.spring()

Next, we will be creating an animation using the Animated.spring() method.

// Example implementation:
Animated.spring(
    someValue,
    {
      toValue: number,
      friction: number
    }
)

We can keep going from the same project, we just need to update a few things. In our constructor, let’s create a value called springValue and set it’s value to .3:

constructor () {
  super()
  this.springValue = new Animated.Value(0.3)
}

Next, let’s delete the animate() method and componentDidMount() method and create a new method called spring():

spring () {
  this.springValue.setValue(0.3)
  Animated.spring(
    this.springValue,
    {
      toValue: 1,
      friction: 1
    }
  ).start()
}

Here, this spring() method does the following steps:

  1. We set the springValue to .3 if it’s not already set to .3
  2. We call Animated.spring, passing in two arguments: a value to animate and a config object. The config object can take any of the following arguments: toValue (number), overshootClamping (boolean), restDisplacementThreshold (number), restSpeedThreshold (number), velocity (number), bounciness (number), speed (number), tension (number), and friction (number). The only required value is toValue, but friction and tension can help us get more control over the spring animation.
  3. We call start() to start the animation.

Now that the animation is set up, let’s attach the animation to a click event in our view, and the animation itself to the same React logo we used before:

<View style={styles.container}>
  <Text
    style={{marginBottom: 100}}
    onPress={this.spring.bind(this)}>Spring</Text>
    <Animated.Image
      style={{ width: 227, height: 200, transform: [{scale: this.springValue}] }}
      source={{uri: 'https://s3.amazonaws.com/media-p.slid.es/uploads/images/1198519/reactjs.png'}}/>
</View>

Here, click event code do the following steps :

  1. We return a Text component attached to the spring() method to an onPress event.
  2. We return the Animated image and attach this.springValue to the scale property.

The spring animation should be working now!

The final code for this animation with a working example is :

import React, { Component } from 'react'
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Animated,
  Image
} from 'react-native'

class animations extends Component {
  constructor () {
    super()
    this.springValue = new Animated.Value(0.3)
  }
  spring () {
    this.springValue.setValue(0.3)
    Animated.spring(
      this.springValue,
      {
        toValue: 1,
        friction: 1,
        tension: 1
      }
    ).start()
  }
  render () {
    return (
      <View style={styles.container}>
        <Text style={{marginBottom: 100}} onPress={this.spring.bind(this)}>Spring</Text>
        <Animated.Image
          style={{ width: 227, height: 200, transform: [{scale: this.springValue}] }}
          source={{uri: 'https://s3.amazonaws.com/media-p.slid.es/uploads/images/1198519/reactjs.png'}}/>
      </View>
    )
  }
}

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

AppRegistry.registerComponent('animations', () => animations)

Note that – Use own image url for example code testing.

The output of the above example is :


4. Animated.parallel()

Animated.parallel() starts an array of animations all at the same time.

Let’s take a look at the api and see how this works:

// API
Animated.parallel(arrayOfAnimations)
// In use:
Animated.parallel([
  Animated.spring(
    animatedValue,
    {
      //config options
    }
  ),
  Animated.timing(
     animatedValue2,
     {
       //config options
     }
  )
])

To get started, let’s go ahead and create the three animated values we will need in our constructor:

constructor () {
  super()
  this.animatedValue1 = new Animated.Value(0)
  this.animatedValue2 = new Animated.Value(0)
  this.animatedValue3 = new Animated.Value(0)
}

Next, we create our animate method and call it in componendDidMount() :

componentDidMount () {
  this.animate()
}
animate () {
  this.animatedValue1.setValue(0)
  this.animatedValue2.setValue(0)
  this.animatedValue3.setValue(0)
  const createAnimation = function (value, duration, easing, delay = 0) {
    return Animated.timing(
      value,
      {
        toValue: 1,
        duration,
        easing,
        delay
      }
    )
  }
  Animated.parallel([
    createAnimation(this.animatedValue1, 2000, Easing.ease),
    createAnimation(this.animatedValue2, 1000, Easing.ease, 1000),
    createAnimation(this.animatedValue3, 1000, Easing.ease, 2000)        
  ]).start()
}

In the animate method, we set the values of all three animated values back to zero. We then create a function called createAnimation() which returns a new animation , taking in the value, duration, easing, and delay as arguments. If no delay is passed in, we set it to zero.

We then call Animated.parallel() passing in the three animations we want to create using createAnimation().

In our render method, we next need to set up our interpolated values:

render () {
  const scaleText = this.animatedValue1.interpolate({
    inputRange: [0, 1],
    outputRange: [0.5, 2]
  })
  const spinText = this.animatedValue2.interpolate({
    inputRange: [0, 1],
    outputRange: ['0deg', '720deg']
  })
  const introButton = this.animatedValue3.interpolate({
    inputRange: [0, 1],
    outputRange: [-100, 400]
  })
  ...
}

Here, the render () method code do the following steps :

1. scaleText — We interpolate our values to be output as a range from 0.5 to 2, we will use this value to scale our text from .5 to 2.

2. spinText — We interpolate our values to be output as a range of 0 degrees to 720 degrees, essentially spinning the item two times.

3. introButton — We interpolate out values to be output as a range of -100 to 400, and will use this as a margin property in our View.

Finally, we render a main View with three Animated.Views:

<View style={[styles.container]}>
  <Animated.View 
    style={{ transform: [{scale: scaleText}] }}>
    <Text>Welcome</Text>
  </Animated.View>
  <Animated.View
    style={{ marginTop: 20, transform: [{rotate: spinText}] }}>
    <Text
      style={{fontSize: 20}}>
      to the App!
    </Text>
  </Animated.View>
  <Animated.View
    style={{top: introButton, position: 'absolute'}}>
    <TouchableHighlight
      onPress={this.animate.bind(this)}
      style={styles.button}>
      <Text
        style={{color: 'white', fontSize: 20}}>
        Click Here To Start
      </Text>
   </TouchableHighlight>
  </Animated.View>
</View>

We use scaleText to scale the first View, spinText to spin the second View, and introButton to animate the margin of the third View.

When animate() is called, all three animations run in parallel. The parallel animations should be working now!

The final code for this animation with a working example is :

import React, { Component } from 'react'
import {
  AppRegistry,
  StyleSheet,
  Text,
  Animated,
  View,
  Easing,
  TouchableHighlight,
  Dimensions
} from 'react-native'

const { width } = Dimensions.get('window')

class animations extends Component {

  constructor () {
    super()
    this.animatedValue1 = new Animated.Value(0)
    this.animatedValue2 = new Animated.Value(0)
    this.animatedValue3 = new Animated.Value(0)
  }

  componentDidMount () {
    this.animate()
  }

  animate () {
    this.animatedValue1.setValue(0)
    this.animatedValue2.setValue(0)
    this.animatedValue3.setValue(0)
    const createAnimation = function (value, duration, easing, delay = 0) {
      return Animated.timing(
       value,
        {
          toValue: 1,
          duration,
          easing,
          delay
        }
      )
    }
    Animated.parallel([
      createAnimation(this.animatedValue1, 2000, Easing.ease),
      createAnimation(this.animatedValue2, 1000, Easing.ease, 1000),
      createAnimation(this.animatedValue3, 1000, Easing.ease, 2000)
    ]).start()
  }

  render () {
    const scaleText = this.animatedValue1.interpolate({
      inputRange: [0, 1],
      outputRange: [0.5, 2]
    })
    const spinText = this.animatedValue2.interpolate({
      inputRange: [0, 1],
      outputRange: ['0deg', '720deg']
    })
    const introButton = this.animatedValue3.interpolate({
      inputRange: [0, 1],
      outputRange: [-100, 400]
    })
    return (
      <View style={[styles.container]}>
        <Animated.View style={{ transform: [{scale: scaleText}] }}>
          <Text>Welcome</Text>
        </Animated.View>
        <Animated.View style={{ marginTop: 20, transform: [{rotate: spinText}] }}>
          <Text style={{fontSize: 20}}>to the App!</Text>
        </Animated.View>
        <Animated.View style={{top: introButton, position: 'absolute'}}>
          <TouchableHighlight onPress={this.animate.bind(this)} style={styles.button}>
            <Text style={{color: 'white', fontSize: 20}}>Click Here To Start</Text>
          </TouchableHighlight>
        </Animated.View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  button: {
    width: width - 40,
    height: 70,
    marginLeft: 20,
    marginRight: 20,
    backgroundColor: 'blue',
    justifyContent: 'center',
    alignItems: 'center'
  }
})

AppRegistry.registerComponent('animations', () => animations)

The output of the above example is :


5. Animated.sequence()

Let’s take a look at the api and see how this animation works:

// API
Animated.sequence(arrayOfAnimations)
// In use
Animated.sequence([
  Animated.timing(
    animatedValue,
    {
      //config options
    }
  ),
  Animated.spring(
     animatedValue2,
     {
       //config options
     }
  )
])

Like Animated.parallel()Animated.sequence() takes an array of animations. Animated.sequence() runs an array of animations in order, waiting for each to complete before starting the next.

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

const arr = []
for (var i = 0; i < 500; i++) {
  arr.push(i)
}

class animations extends Component {

  constructor () {
    super()
    this.animatedValue = []
    arr.forEach((value) => {
      this.animatedValue[value] = new Animated.Value(0)
    })
  }

  componentDidMount () {
    this.animate()
  }

  animate () {
    const animations = arr.map((item) => {
      return Animated.timing(
        this.animatedValue[item],
        {
          toValue: 1,
          duration: 50
        }
      )
    })
    Animated.sequence(animations).start()
  }

  render () {
    const animations = arr.map((a, i) => {
      return <Animated.View key={i} style={{opacity: this.animatedValue[a], height: 20, width: 20, backgroundColor: 'red', marginLeft: 3, marginTop: 3}} />
    })
    return (
      <View style={styles.container}>
        {animations}
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    flexWrap: 'wrap'
  }
})

AppRegistry.registerComponent('animations', () => animations);

Because the apis for Animated.sequence() and Animated.parallel() are so similar, taking an array of animations, we are not going to repeat the walkthrough of each method.

The main thing to notice here that is different is that we are creating our Animated.Values with a loop since we are animating so many values. We are also rendering our Animated.Views with a map function returning a new Animated.View for each item in the array.

The sequence of animations should be working now! The output of the above example is :


6. Animated.stagger()

Let’s take a look at the api and see how this animation works:

// API
Animated.stagger(delay, arrayOfAnimations)
// In use:
Animated.stagger(1000, [
  Animated.timing(
    animatedValue,
    {
      //config options
    }
  ),
  Animated.spring(
     animatedValue2,
     {
       //config options
     }
  )
])

Like Animated.parallel() and Animated.sequence(), Animated.Stagger also takes an array of animations, but these animations are started in sequence with successive delays.

The main difference here is the first argument, the delay that will be applied to each animation.

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

const arr = []
for (var i = 0; i < 500; i++) {
  arr.push(i)
}

class animations extends Component {

  constructor () {
    super()
    this.animatedValue = []
    arr.forEach((value) => {
      this.animatedValue[value] = new Animated.Value(0)
    })
  }

  componentDidMount () {
    this.animate()
  }

  animate () {
    const animations = arr.map((item) => {
      return Animated.timing(
        this.animatedValue[item],
        {
          toValue: 1,
          duration: 4000
        }
      )
    })
    Animated.stagger(10, animations).start()
  }

  render () {
    const animations = arr.map((a, i) => {
      return <Animated.View key={i} style={{opacity: this.animatedValue[a], height: 20, width: 20, backgroundColor: 'red', marginLeft: 3, marginTop: 3}} />
    })
    return (
      <View style={styles.container}>
        {animations}
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    flexWrap: 'wrap'
  }
})

AppRegistry.registerComponent('animations', () => animations);

The staggered animations should be working now! The output of above example is :

That’s all about in this article.


Conclusion

In this article, We understood about Animation Animation Animated API in React Native. Animation is an important part of user experience design. It serves as feedback on user actions, informs users of system status, and guides them on how to interact with the interface. We discussed how to implement Animations using Animated Api in React native with some example.

Thanks for reading ! I hope you enjoyed and learned about the Animation Animated API 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 – Understanding Animations In React Native

Hello Readers, CoolMonkTechie heartily welcomes you in this article (Understanding Animations In React Native).

In this article, We will learn about Animations in React Native. Animations are very important to create a great user experience. Stationary objects must overcome inertia as they start moving. Objects in motion have momentum and rarely come to a stop immediately. Animations allow us to convey physically believable motion in our interface.

A famous quote about learning is :

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

So Let’s begin.


Animation Systems

React Native provides two complementary animation systems: 

  • Animated for granular and interactive control of specific values. It is a built-in API for animating component styles.
  • LayoutAnimation for animated global layout transactions. It is a built-in API for animating between 2 component hierarchies (think “magic move”), although still considered experimental.

Most animations will use Animated.


1. Animated

The Animated API is designed to concisely express a wide variety of interesting animation and interaction patterns in a very performant way. Animated focuses on declarative relationships between inputs and outputs, with configurable transforms in between, and start/stop methods to control time-based animation execution.

Animated exports six animatable component types: ViewTextImageScrollViewFlatList and SectionList, but we can also create own using Animated.createAnimatedComponent().

The Animated API lets us animate component styles.

For example, a container view that fades in when it is mounted may look like this:

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

const FadeInView = (props) => {
  const fadeAnim = useRef(new Animated.Value(0)).current  // Initial value for opacity: 0

  React.useEffect(() => {
    Animated.timing(
      fadeAnim,
      {
        toValue: 1,
        duration: 10000,
      }
    ).start();
  }, [fadeAnim])

  return (
    <Animated.View                 // Special animatable View
      style={{
        ...props.style,
        opacity: fadeAnim,         // Bind opacity to animated value
      }}
    >
      {props.children}
    </Animated.View>
  );
}

// You can then use your `FadeInView` in place of a `View` in your components:
export default () => {
  return (
    <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
      <FadeInView style={{width: 250, height: 50, backgroundColor: 'powderblue'}}>
        <Text style={{fontSize: 28, textAlign: 'center', margin: 10}}>Fading in</Text>
      </FadeInView>
    </View>
  )
}

Let’s break down what’s happening here.  In the FadeInView constructor, a new Animated.Value called fadeAnim is initialized as part of state. The opacity property on the View is mapped to this animated value. Behind the scenes, the numeric value is extracted and used to set opacity.

When the component mounts, the opacity is set to 0. Then, an easing animation is started on the fadeAnim animated value, which will update all of its dependent mappings (in this case, only the opacity) on each frame as the value animates to the final value of 1.

This is done in an optimized way that is faster than calling setState and re-rendering. Because the entire configuration is declarative, we will be able to implement further optimizations that serialize the configuration and runs the animation on a high-priority thread.


Configuring animations

Animations are heavily configurable. Custom and predefined easing functions, delays, durations, decay factors, spring constants, and more can all be tweaked depending on the type of animation.

Animated provides several animation types, the most commonly used one being Animated.timing(). It supports animating a value over time using one of various predefined easing functions, or we can use own. Easing functions are typically used in animation to convey gradual acceleration and deceleration of objects.

By default, timing will use an easeInOut curve that conveys gradual acceleration to full speed and concludes by gradually decelerating to a stop. We can specify a different easing function by passing an easing parameter. Custom duration or even a delay before the animation starts is also supported.

For example, if we want to create a 2-second long animation of an object that slightly backs up before moving to its final position:

Animated.timing(this.state.xPosition, {
  toValue: 100,
  easing: Easing.back(),
  duration: 2000
}).start();


Composing animations

Animations can be combined and played in sequence or in parallel. Sequential animations can play immediately after the previous animation has finished, or they can start after a specified delay. The Animated API provides several methods, such as sequence() and delay(), each of which take an array of animations to execute and automatically calls start()/stop() as needed.

For example, the following animation coasts to a stop, then it springs back while twirling in parallel:

Animated.sequence([
  // decay, then spring to start and twirl
  Animated.decay(position, {
    // coast to a stop
    velocity: { x: gestureState.vx, y: gestureState.vy }, // velocity from gesture release
    deceleration: 0.997
  }),
  Animated.parallel([
    // after decay, in parallel:
    Animated.spring(position, {
      toValue: { x: 0, y: 0 } // return to start
    }),
    Animated.timing(twirl, {
      // and twirl
      toValue: 360
    })
  ])
]).start(); // start the sequence group

If one animation is stopped or interrupted, then all other animations in the group are also stopped. Animated.parallel has a stopTogether option that can be set to false to disable this.


Combining animated values

We can combine two animated values via addition, multiplication, division, or modulo to make a new animated value.

There are some cases where an animated value needs to invert another animated value for calculation. An example is inverting a scale (2x –> 0.5x):

const a = new Animated.Value(1);
const b = Animated.divide(1, a);

Animated.spring(a, {
  toValue: 2
}).start();


Interpolation

Each property can be run through an interpolation first. An interpolation maps input ranges to output ranges, typically using a linear interpolation but also supports easing functions. By default, it will extrapolate the curve beyond the ranges given, but we can also have it clamp the output value.

A basic mapping to convert a 0-1 range to a 0-100 range would be:

value.interpolate({
  inputRange: [0, 1],
  outputRange: [0, 100]
});

For example, we may want to think about our Animated.Value as going from 0 to 1, but animate the position from 150px to 0px and the opacity from 0 to 1. This can be done by modifying style from the example above like so:

style={{
    opacity: this.state.fadeAnim, // Binds directly
    transform: [{
      translateY: this.state.fadeAnim.interpolate({
        inputRange: [0, 1],
        outputRange: [150, 0]  // 0 : 150, 0.5 : 75, 1 : 0
      }),
    }],
  }}

interpolate() supports multiple range segments as well, which is handy for defining dead zones and other handy tricks. For example, to get a negation relationship at -300 that goes to 0 at -100, then back up to 1 at 0, and then back down to zero at 100 followed by a dead-zone that remains at 0 for everything beyond that, we could do:

value.interpolate({
  inputRange: [-300, -100, 0, 100, 101],
  outputRange: [300, 0, 1, 0, 0]
});

Which would map like so:

Input | Output
------|-------
  -400|    450
  -300|    300
  -200|    150
  -100|      0
   -50|    0.5
     0|      1
    50|    0.5
   100|      0
   101|      0
   200|      0

interpolate() also supports mapping to strings, allowing us to animate colors as well as values with units. For example, if we wanted to animate a rotation we could do:

value.interpolate({
  inputRange: [0, 360],
  outputRange: ['0deg', '360deg']
});

interpolate() also supports arbitrary easing functions, many of which are already implemented in the Easing module. interpolate() also has configurable behavior for extrapolating the outputRange. We can set the extrapolation by setting the extrapolateextrapolateLeft, or extrapolateRight options. The default value is extend but we can use clamp to prevent the output value from exceeding outputRange.


Tracking dynamic values

Animated values can also track other values by setting the toValue of an animation to another animated value instead of a plain number. For example, a “Chat Heads” animation like the one used by Messenger on Android could be implemented with a spring() pinned on another animated value, or with timing() and a duration of 0 for rigid tracking. They can also be composed with interpolations:

Animated.spring(follower, { toValue: leader }).start();
Animated.timing(opacity, {
  toValue: pan.x.interpolate({
    inputRange: [0, 300],
    outputRange: [1, 0]
  })
}).start();

The leader and follower animated values would be implemented using Animated.ValueXY()ValueXY is a handy way to deal with 2D interactions, such as panning or dragging. It is a basic wrapper that contains two Animated.Value instances and some helper functions that call through to them, making ValueXY a drop-in replacement for Value in many cases. It allows us to track both x and y values in the example above.


Tracking gestures

Gestures, like panning or scrolling, and other events can map directly to animated values using Animated.event. This is done with a structured map syntax so that values can be extracted from complex event objects. The first level is an array to allow mapping across multiple args, and that array contains nested objects.

For example, when working with horizontal scrolling gestures, we would do the following in order to map event.nativeEvent.contentOffset.x to scrollX (an Animated.Value):

onScroll={Animated.event(
   // scrollX = e.nativeEvent.contentOffset.x
   [{ nativeEvent: {
        contentOffset: {
          x: scrollX
        }
      }
    }]
 )}

The following example implements a horizontal scrolling carousel where the scroll position indicators are animated using the Animated.event used in the ScrollView.

import React, { useRef } from "react";
import {
  SafeAreaView,
  ScrollView,
  Text,
  StyleSheet,
  View,
  ImageBackground,
  Animated,
  useWindowDimensions
} from "react-native";

const images = new Array(6).fill('https://images.unsplash.com/photo-1556740749-887f6717d7e4');

const App = () => {
  const scrollX = useRef(new Animated.Value(0)).current;

  const { width: windowWidth } = useWindowDimensions();

  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.scrollContainer}>
        <ScrollView
          horizontal={true}
          style={styles.scrollViewStyle}
          pagingEnabled
          showsHorizontalScrollIndicator={false}
          onScroll={Animated.event([
            {
              nativeEvent: {
                contentOffset: {
                  x: scrollX
                }
              }
            }
          ])}
          scrollEventThrottle={1}
        >
          {images.map((image, imageIndex) => {
            return (
              <View
                style={{ width: windowWidth, height: 250 }}
                key={imageIndex}
              >
                <ImageBackground source={{ uri: image }} style={styles.card}>
                  <View style={styles.textContainer}>
                    <Text style={styles.infoText}>
                      {"Image - " + imageIndex}
                    </Text>
                  </View>
                </ImageBackground>
              </View>
            );
          })}
        </ScrollView>
        <View style={styles.indicatorContainer}>
          {images.map((image, imageIndex) => {
            const width = scrollX.interpolate({
              inputRange: [
                windowWidth * (imageIndex - 1),
                windowWidth * imageIndex,
                windowWidth * (imageIndex + 1)
              ],
              outputRange: [8, 16, 8],
              extrapolate: "clamp"
            });
            return (
              <Animated.View
                key={imageIndex}
                style={[styles.normalDot, { width }]}
              />
            );
          })}
        </View>
      </View>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center"
  },
  scrollContainer: {
    height: 300,
    alignItems: "center",
    justifyContent: "center"
  },
  card: {
    flex: 1,
    marginVertical: 4,
    marginHorizontal: 16,
    borderRadius: 5,
    overflow: "hidden",
    alignItems: "center",
    justifyContent: "center"
  },
  textContainer: {
    backgroundColor: "rgba(0,0,0, 0.7)",
    paddingHorizontal: 24,
    paddingVertical: 8,
    borderRadius: 5
  },
  infoText: {
    color: "white",
    fontSize: 16,
    fontWeight: "bold"
  },
  normalDot: {
    height: 8,
    width: 8,
    borderRadius: 4,
    backgroundColor: "silver",
    marginHorizontal: 4
  },
  indicatorContainer: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center"
  }
});

export default App;

The output of the above example is :

When using PanResponder, we could use the following code to extract the x and y positions from gestureState.dx and gestureState.dy. We use a null in the first position of the array, as we are only interested in the second argument passed to the PanResponder handler, which is the gestureState.

onPanResponderMove={Animated.event(
  [null, // ignore the native event
  // extract dx and dy from gestureState
  // like 'pan.x = gestureState.dx, pan.y = gestureState.dy'
  {dx: pan.x, dy: pan.y}
])}


Responding to the current animation value

We may notice that there is no clear way to read the current value while animating. This is because the value may only be known in the native runtime due to optimizations. If we need to run JavaScript in response to the current value, there are two approaches:

  • spring.stopAnimation(callback) will stop the animation and invoke callback with the final value. This is useful when making gesture transitions.
  • spring.addListener(callback) will invoke callback asynchronously while the animation is running, providing a recent value. This is useful for triggering state changes, for example snapping a bobble to a new option as the user drags it closer, because these larger state changes are less sensitive to a few frames of lag compared to continuous gestures like panning which need to run at 60 fps.

Animated is designed to be fully serializable so that animations can be run in a high performance way, independent of the normal JavaScript event loop. This does influence the API, so keep that in mind when it seems a little trickier to do something compared to a fully synchronous system. We need to check out Animated.Value.addListener as a way to work around some of these limitations, but use it sparingly since it might have performance implications in the future.


Using the native driver

The Animated API is designed to be serializable. By using the native driver, we send everything about the animation to native before starting the animation, allowing native code to perform the animation on the UI thread without having to go through the bridge on every frame. Once the animation has started, the JS thread can be blocked without affecting the animation.

Using the native driver for normal animations is straightforward. We can add useNativeDriver: true to the animation config when starting it.

Animated.timing(this.state.animatedValue, {
  toValue: 1,
  duration: 500,
  useNativeDriver: true // <-- Add this
}).start();

Animated values are only compatible with one driver so if we use native driver when starting an animation on a value, make sure every animation on that value also uses the native driver.

The native driver also works with Animated.event. This is especially useful for animations that follow the scroll position as without the native driver, the animation will always run a frame behind the gesture due to the async nature of React Native.

<Animated.ScrollView // <-- Use the Animated ScrollView wrapper
  scrollEventThrottle={1} // <-- Use 1 here to make sure no events are ever missed
  onScroll={Animated.event(
    [
      {
        nativeEvent: {
          contentOffset: { y: this.state.animatedValue }
        }
      }
    ],
    { useNativeDriver: true } // <-- Add this
  )}>
  {content}
</Animated.ScrollView>

Not everything we can do with Animated is currently supported by the native driver. The main limitation is that we can only animate non- layout properties: things like transform and opacity will work, but Flexbox and position properties will not. When using Animated.event, it will only work with direct events and not bubbling events. This means it does not work with PanResponder but does work with things like ScrollView#onScroll.

When an animation is running, it can prevent VirtualizedList components from rendering more rows. If we need to run a long or looping animation while the user is scrolling through a list, we can use isInteraction: false in our animation’s config to prevent this issue.


2. LayoutAnimation API

LayoutAnimation allows us to globally configure create and update animations that will be used for all views in the next render/layout cycle. This is useful for doing Flexbox layout updates without bothering to measure or calculate specific properties in order to animate them directly, and is especially useful when layout changes may affect ancestors, for example a “see more” expansion that also increases the size of the parent and pushes down the row below which would otherwise require explicit coordination between the components in order to animate them all in sync.

Note that although LayoutAnimation is very powerful and can be quite useful, it provides much less control than Animated and other animation libraries, so we may need to use another approach if we can’t get LayoutAnimation to do what you want.

Note that in order to get this to work on Android, we need to set the following flags via UIManager:

UIManager.setLayoutAnimationEnabledExperimental &&
  UIManager.setLayoutAnimationEnabledExperimental(true);

This example uses a preset value, we can customize the animations as we need,

import React from 'react';
import {
  NativeModules,
  LayoutAnimation,
  Text,
  TouchableOpacity,
  StyleSheet,
  View,
} from 'react-native';

const { UIManager } = NativeModules;

UIManager.setLayoutAnimationEnabledExperimental &&
  UIManager.setLayoutAnimationEnabledExperimental(true);

export default class App extends React.Component {
  state = {
    w: 100,
    h: 100,
  };

  _onPress = () => {
    // Animate the update
    LayoutAnimation.spring();
    this.setState({ w: this.state.w + 15, h: this.state.h + 15 })
  }

  render() {
    return (
      <View style={styles.container}>
        <View style={[styles.box, { width: this.state.w, height: this.state.h }]} />
        <TouchableOpacity onPress={this._onPress}>
          <View style={styles.button}>
            <Text style={styles.buttonText}>Press me!</Text>
          </View>
        </TouchableOpacity>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  box: {
    width: 200,
    height: 200,
    backgroundColor: 'red',
  },
  button: {
    backgroundColor: 'black',
    paddingHorizontal: 20,
    paddingVertical: 15,
    marginTop: 15,
  },
  buttonText: {
    color: '#fff',
    fontWeight: 'bold',
  },
});

The output of the above example is :

That’s all about in this article.

Related Other Articles / Posts


Conclusion

In this article, We understood about Animations in React Native. Animation is an important part of user experience design. It serves as feedback on user actions, informs users of system status, and guides them on how to interact with the interface. 

Thanks for reading ! I hope you enjoyed and learned about the Animations 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 Touchable Components In React Native ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (React Native – How To Use Touchable Components In React Native?).

In this article, we will understand about how to use Touchable Components in React Native. Users interact with mobile apps mainly through touch. They can use a combination of gestures, such as tapping on a button, scrolling a list, or zooming on a map. React Native provides components to handle all sorts of common gestures, as well as a comprehensive gesture responder system to allow for more advanced gesture recognition, but the one component we will most likely be interested in is the basic Button. This article demonstrates the kinds of touchable with examples in React Native.

A famous quote about learning is :

” Anyone who stops learning is old, whether at twenty or eighty. Anyone who keeps learning stays young. The greatest thing in life is to keep your mind young. “

So Let’s begin.


Displaying a basic button

Button provides a basic button component that is rendered nicely on all platforms. The minimal example to display a button looks like this:

<Button
  onPress={() => {
    alert('You tapped the button!');
  }}
  title="Press Me"
/>

This will render a blue label on iOS, and a blue rounded rectangle with light text on Android. Pressing the button will call the “onPress” function, which in this case displays an alert popup. If we like, we can specify a “color” prop to change the color of our button.

We can see the Button component using the example below. We can select which platform our app is previewed in by clicking on the toggle in the bottom right, then click on “Tap to Play” to preview the app.

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

export default class ButtonBasics extends Component {
  _onPressButton() {
    alert('You tapped the button!')
  }

  render() {
    return (
      <View style={styles.container}>
        <View style={styles.buttonContainer}>
          <Button
            onPress={this._onPressButton}
            title="Press Me"
          />
        </View>
        <View style={styles.buttonContainer}>
          <Button
            onPress={this._onPressButton}
            title="Press Me"
            color="#841584"
          />
        </View>
        <View style={styles.alternativeLayoutButtonContainer}>
          <Button
            onPress={this._onPressButton}
            title="This looks great!"
          />
          <Button
            onPress={this._onPressButton}
            title="OK!"
            color="#841584"
          />
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
   flex: 1,
   justifyContent: 'center',
  },
  buttonContainer: {
    margin: 20
  },
  alternativeLayoutButtonContainer: {
    margin: 20,
    flexDirection: 'row',
    justifyContent: 'space-between'
  }
});

The result of above example is displayed below :


Touchables

In React Native, most “buttons” are actually implemented using Touchable components. Like Button, these components support an onPress prop. However, unlike Button, these components support custom styling – essentially a Touchable is a View that can be pressed.

Touchables have a variety of other props, like onPressIn and onPressOut, which give us more control over the behavior of the button. We can use these props to run custom animations.


Kinds of Touchable

Although we can run custom animations, most of the time, we use one of 2 built-in animations: a fade in opacity, or a change of color. There are preconfigured touchable components for each of these: TouchableOpacity and TouchableHighlight.

Which “Touchable” component we use will depend on what kind of feedback we want to provide:

  • Generally, we can use TouchableHighlight anywhere we would use a button or link on web. The view’s background will be darkened when the user presses down on the button.
  • We may consider using TouchableNativeFeedback on Android to display ink surface reaction ripples that respond to the user’s touch.
  • TouchableOpacity can be used to provide feedback by reducing the opacity of the button, allowing the background to be seen through while the user is pressing down.
  • If we need to handle a tap gesture but we don’t want any feedback to be displayed, use TouchableWithoutFeedback.

In some cases, we may want to detect when a user presses and holds a view for a set amount of time. These long presses can be handled by passing a function to the onLongPress props of any of the “Touchable” components.


Example

Let’s see all of these in action:

import React, { Component } from 'react';
import { Platform, StyleSheet, Text, TouchableHighlight, TouchableOpacity, TouchableNativeFeedback, TouchableWithoutFeedback, View } from 'react-native';

export default class Touchables extends Component {
  _onPressButton() {
    alert('You tapped the button!')
  }

  _onLongPressButton() {
    alert('You long-pressed the button!')
  }

  render() {
    return (
      <View style={styles.container}>
        <TouchableHighlight onPress={this._onPressButton} underlayColor="white">
          <View style={styles.button}>
            <Text style={styles.buttonText}>TouchableHighlight</Text>
          </View>
        </TouchableHighlight>
        <TouchableOpacity onPress={this._onPressButton}>
          <View style={styles.button}>
            <Text style={styles.buttonText}>TouchableOpacity</Text>
          </View>
        </TouchableOpacity>
        <TouchableNativeFeedback
            onPress={this._onPressButton}
            background={Platform.OS === 'android' ? TouchableNativeFeedback.SelectableBackground() : ''}>
          <View style={styles.button}>
            <Text style={styles.buttonText}>TouchableNativeFeedback {Platform.OS !== 'android' ? '(Android only)' : ''}</Text>
          </View>
        </TouchableNativeFeedback>
        <TouchableWithoutFeedback
            onPress={this._onPressButton}
            >
          <View style={styles.button}>
            <Text style={styles.buttonText}>TouchableWithoutFeedback</Text>
          </View>
        </TouchableWithoutFeedback>
        <TouchableHighlight onPress={this._onPressButton} onLongPress={this._onLongPressButton} underlayColor="white">
          <View style={styles.button}>
            <Text style={styles.buttonText}>Touchable with Long Press</Text>
          </View>
        </TouchableHighlight>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    paddingTop: 60,
    alignItems: 'center'
  },
  button: {
    marginBottom: 30,
    width: 260,
    alignItems: 'center',
    backgroundColor: '#2196F3'
  },
  buttonText: {
    textAlign: 'center',
    padding: 20,
    color: 'white'
  }
});

The result of above example is displayed below :


Scrolling and swiping

Gestures commonly used on devices with touchable screens include swipes and pans. These allow the user to scroll through a list of items, or swipe through pages of content. 

That’s all about in this article.


Conclusion

In this article, We understood about how to use Touchable Components in React Native.

Thanks for reading ! I hope you enjoyed and learned about the Touchable 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 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 Hooks In React Native ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (How To Use Hooks In React Native ?).

In this article, we will understand about how to use Hooks in react native. Hooks are specially-implemented functions that let us add functionality to React components beyond just creating and returning React elements. This article demonstrates the built-in hooks usage in react native application.

A famous quote about learning is :

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

So Let’s begin.


React Hooks

” React Hooks are a new addition in React 16.8 that let you use state and other React features without writing a class component. In other words, Hooks are functions that let you “hook into” React state and lifecycle features from function components. (They do not work inside class components.)”

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class. It mainly uses to handle the state and side effects in react functional component. React Hooks are a way to use stateful functions inside a functional component. Hooks don’t work inside classes — they let you use React without classesReact provides a few built-in Hooks like useState and useEffect. The React hooks do :

  • Best practices
  • Easy to under understand
  • Easy to test
  • Increases the performance and so on.


Rules and Linting

Hooks aren’t regular functions; they have to be written in a certain way. To dive deeper into this topic, check out:

ReactJS – How to Effectively Think In React Hooks ?

When using hooks, we typically want to use eslint and the react-hooks plugin. Hooks are powerful, but can be unintuitive at first, and this tool catches a lot of mistakes before we ever run our code.


In-built React Hooks APIs

We’ll look at the following built-in hooks in more detail:

  • useState – Persist state within a component function
  • useReducer – Similar to useState, but for state that involves multiple sub-values
  • useEffect – Perform side effects within our component functions
  • useRef – Wrap a mutable value


1. useState

The useState hook lets us “remember” a value within a component function. Since our component function may be called many times throughout the lifecycle of the component, any variable we declare normally (i.e. with let myVar = ...) will get reset. With useState, React can remember a state variable for us, making sure it gets passed into our component instance correctly.


API

The useState hook takes a single argument, our initial state, and returns an array containing two elements:

  • state – the current state
  • setState – a function to update our state

Syntax –  const [state, setState] = useState(initialValue)


Example

In this example, we’ll use useState to append to an array.

The useState hook can store any type of value: a number, a string, an array, an object, etc.

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

const randomDiceRoll = () => Math.floor(Math.random() * 6) + 1

export default function App() {
  const [diceRolls, setDiceRolls] = useState([])

  return (
    <View>
      <Button
        title="Roll dice!"
        onPress={() => {
          setDiceRolls([...diceRolls, randomDiceRoll()])
        }}
      />
      {diceRolls.map((diceRoll, index) => (
        <Text style={{ fontSize: 24 }} key={index}>
          {diceRoll}
        </Text>
      ))}
    </View>
  )
}

The result of above example is displayed below :


Updating mutable state values

Note how when we call setDiceRoll, we’re not pushing the integer returned from randomDiceRoll() into the diceRolls array. Instead, we return a new array containing the destructured diceRolls array and the newly randomized dice roll. Why?

Hooks can tell React to re-run our component function and update the UI. The useState hook tells React to re-run our component function whenever we call setDiceRolls with a different value. Internally, useState then compares the current value of diceRolls with the value we passed to setDiceRolls using ===. If we’re using a mutable value like an array, and we only change its contents, useState won’t detect that change and won’t tell React to re-run our component function. This will result in our UI displaying old/stale data. To avoid this problem we need to create a new array, so that useState will detect that our data changed and display the newest data.


2. useReducer

The useReducer hook is similar to useState, but gives us a more structured approach for updating complex values.

We typically use useReducer when our state has multiple sub-values, e.g. an object containing keys that we want to update independently.


API

The useReducer hook requires 2 arguments, and has an optional 3rd argument:

  • reducer – a pure function that takes a state and an action, and returns a new state value based on the action
  • initialState – any initial state value, just like useState
  • initializer (optional) – a function called to lazily instantiate the initialState (this is uncommon)

The useReducer hook returns the current state, and a dispatch function to update the state.


Example

In this example, we store both a first and last name in a single state object with useReducer.

When we type a new first name, dispatch is called with { type: 'first', value: text } as its argument. This argument gets passed to the reducer as action. Then the reducer follows the switch case logic case 'first' and returns the new state: the current last name (from ...state) and the new first name contained in the action as action.value.

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

function reducer(state, action) {
  switch (action.type) {
    case 'first':
      return { ...state, first: action.value }
    case 'last':
      return { ...state, last: action.value }
  }
}

export default function App() {
  const [state, dispatch] = useReducer(reducer, { first: '', last: '' })

  return (
    <View>
      <TextInput
        style={{ fontSize: 32 }}
        placeholder="First"
        value={state.first}
        onChangeText={(text) => {
          dispatch({ type: 'first', value: text })
        }}
      />
      <TextInput
        style={{ fontSize: 32 }}
        placeholder="Last"
        value={state.last}
        onChangeText={(text) => {
          dispatch({ type: 'last', value: text })
        }}
      />
      <Text style={{ fontSize: 32 }}>
        Hello {state.first} {state.last}
      </Text>
    </View>
  )
}

The result of above example is displayed below :


3. useEffect

We use the useEffect hook to call functions with side effects within our components.


API

The useEffect hook takes 2 arguments:

  • callback – a function with side effects
  • dependencies – an optional array containing dependency values

When our component function runs, the callback will be called if any dependencies have changed since the last time the component function ran.


Example

In this example, we’ll log to the console any time the count is a multiple of 3. The callback is called every time the countEvery3 changes, since countEvery3 is listed as a dependency.

import React, { useState, useEffect } from 'react'
import { Button } from 'react-native'

export default function App() {
  const [count, setCount] = useState(0)
  const countEvery3 = Math.floor(count / 3)

  useEffect(() => {
    console.log(countEvery3)
  }, [countEvery3])

  return (
    <Button
      title={`Increment ${count}`}
      onPress={() => {
        setCount(count + 1)
      }}
    />
  )
}

The result of above example is displayed below :


Undefined or empty dependency array

If the dependency array is empty or undefineduseEffect will have a different behavior:

  • [] – the callback is called only once, right after the component renders for the first time.
  • undefined – the callback is called on every component render (every time the component function runs).


undefined dependencies

Here the dependency array is undefined, so our callback will run every time our component function runs, e.g. any time we click the button and useState tells our component to re-run.

import React, { useState, useEffect } from 'react'
import { Button } from 'react-native'

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

  useEffect(() => {
    console.log('Incremented!')
  })

  return (
    <Button
      title={`Increment ${count}`}
      onPress={() => {
        setCount(count + 1)
      }}
    />
  )
}

The result of above example is displayed below :


Empty dependencies

Here the dependency array is empty, so our callback will only run once (and therefore only log one time).

import React, { useState, useEffect } from 'react'
import { Button } from 'react-native'

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

  useEffect(() => {
    console.log('Only once!')
  }, [])

  return (
    <Button
      title={`Increment ${count}`}
      onPress={() => {
        setCount(count + 1)
      }}
    />
  )
}

The result of above example is displayed below :


4. useRef

With useRef, we can create and update a single mutable value that exists for the lifetime of the component instance.

After assigning the ref to a variable, we use .current to access the mutable value.


Example

In this example, we store the return value of setInterval, which is an interval id, so that we can later call clearInterval.

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

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

  useEffect(() => {
    intervalRef.current = setInterval(
      () => setCount((count) => count + 1),
      1000
    )

    return () => {
      clearInterval(intervalRef.current)
    }
  }, [])

  return (
    <View>
      <Text style={{ fontSize: 120 }}>{count}</Text>
      <Button
        title="Stop"
        onPress={() => {
          clearInterval(intervalRef.current)
        }}
      />
    </View>
  )
}

The result of above example is displayed below :


5. Custom Hooks

We can compose built-in hooks to create new ones. We should still use the use prefix for our function name.


Example

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

function useInterval(callback, delay) {
  const savedCallback = useRef()

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback
  }, [callback])

  // Set up the interval.
  useEffect(() => {
    if (delay !== null) {
      let id = setInterval(() => {
        savedCallback.current()
      }, delay)
      return () => clearInterval(id)
    }
  }, [delay])
}

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

  useInterval(() => {
    setCount(count + 1)
  }, 1000)

  return <Text style={{ fontSize: 120 }}>{count}</Text>
}

That’s all about in this article.


Conclusion

In this article, We understood about how to use Hooks in React Native. This article demonstrated In-built Hooks APIs Usage with examples in React Native application.

Thanks for reading ! I hope you enjoyed and learned about the Hook 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 Make Conditional Rendering Safer In React Native ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (How To Make Conditional Rendering Safer In React Native ?).

In this article, We will learn how to use conditional rendering safer in react native. Sometimes, depending on the conditions, we need to perform various actions or present the particular view. To do this, we will use the conditional statements.

Very soon after start of creating first app every developer needs to render component in one way or another depending on props. When one start searching, the first answer is inside React documentation. The answer is “Conditional Rendering”. But after a while many of us starts facing errors in React Native (or wrong rendering in React for web) that seems to jump on occasionally to reappear some time later. This article will explain what is happening and how to prevent further mistakes.

A famous quote about learning is :

” That is what learning is. You suddenly understand something you’ve understood all your life, but in a new way.”

So Let’s begin.


Conditional Rendering

Conditional rendering using inline If with logical && (AND) operator as React docs says:

You may embed any expressions in JSX by wrapping them in curly braces. This includes the JavaScript logical && operator. It can be handy for conditionally including an element — React docs: Conditional Rendering


Example 1Text Example

{someValue && (
  <View style={styles.field}>
    <Text>{someValue}</Text>
  </View>
)}

This handy solution is used by many and it’s nothing new for our community to see in the code. How and why it can crash your React Native app?

When using it widely in our App without proper attention sooner or later we will see this error (or worse scenario our users will see that the app crashed):

Invariant Violation: Text strings must be rendered within a <Text> component.

Then we see such an error in our logs and scratch our head because usually it works, it may crash for one particular data entry or after some small API change. What happened? Hint: someValue type matters.


Example 2 – Array Example

Another common example of javascript operator wrong usage is rendering something is array contains any elements:

// Sooner or later this code will surprise users.
// Just wait for an empty array.
{dataEntries.length && (
  <View>
    <Text>Visible only when array is not empty</Text>
  </View>
)}

Above example looks fine at a first glance. Array’s length will be 0 which is falsy thus condition is not satisfied and following component is not rendered — simple. This reasoning is partially good but author might forgot about one little fact that will surprise users at some point. Let’s take a closer look.


How logical AND && operator in JavaScript works?

Let’s see the docs again:

OperatorSyntaxDescription
Logical AND (&&)expr1 && expr2If expr1 can be converted to true, returns expr2; else, returns expr1.

If a value can be converted to true, the value is so-called truthy. If a value can be converted to false, the value is so-called falsy.

Examples of expressions that can be converted to false are:

  • null;
  • NaN;
  • 0;
  • empty string ("" or '' or ``);
  • undefined.


String Variable

Boolean('hello world')
// -> true

Boolean('')
// -> false

Boolean(' ')	// space
// -> true

'' && 'conditionally returned string'
// -> ''

'hello world' && 'conditionally returned string'
// -> 'conditionally returned string'

Empty string is falsy so AND operator will return '' because the condition is not fulfilled. Returning '' directly into ReactNative JSX will produce error Text strings must be rendered within a <Text> component and cause crash.


Numeric Variable

Boolean(-1)
// -> true

Boolean(0)
// -> false

Boolean(1)
// -> true

0 && 'conditionally returned string'
// -> 0

1 && 'conditionally returned string'
// -> 'conditionally returned string'

Zero is falsy so logical AND operator will return 0 as the condition is not met. Returning 0 into ReactNative JSX will cause crash with Invariant Violation error again.


Other Variable Types

Boolean(null)
// -> false

Boolean(undefined)
// -> false

Boolean({})
// -> true

Boolean([])		// worth noting!
// -> true

From the above examples the most interesting from React Native developer’s point of view is array. Usually when we put array into conditional render we would like not to render anything if array is empty. Passing an empty array into logical expression without any preparation will mislead us. What one would need to do is to check whether length exists and is equal to 0.


Why React Native crashes?

Rendering string in React Native must be wrapped with <Text>...</Text> component. But when we want to hide entire component when variable is empty with conditional rendering it may return an empty string directly into JSX. For example:

let optionalStr = ''

// [...] some logic that leaves `optionalStr` empty

{optionalStr && <Text>{optionalStr}</Text>} // crash

Now we know that above condition is not fulfilled therefore logical AND operator will return optionalStr directly into main JSX.


What about a numeric variable?

Normally, JavaScript expressions inserted in JSX will evaluate to a string, a React element, or a list of those things. […] — React docs: JSX in Depth

React tries to convert results of our expressions into a string, React element or array. This is why we see Invariant Violation: Text strings must be rendered within a <Text> component even if our variable was Number. It may be misleading while searching for this bug in a production code.


Why Is It Hard To Find React Native Conditional Render Error?

This error is sneaky because it may take a long time before it shows up. Our code may be working like a charm without any issues for months and suddenly something changes on API and type of that nullable variable changes suddenly to empty string or 0.

Why it works with variables that are null or undefined then? It will also work for booleans. React creators make our life easier and by default such variables are ignored in a JSX tree. It is special case and it will not be rendered.

React will also not crash when we put empty array directly into JSX as arrays can render multiple elements.

// below expressions will not crash your React Native app
<View>
  {false}
  {true}
  {null}
  {undefined}
  {[]}
</View>


Different Options To Make Conditional Rendering Safer

We just make sure to convert every variable into Boolean before using logical AND && operator.

We can do it multiple ways:

  • Double negation — !!dangerousData
  • Classic conversion — Boolean(dangerousData)
  • Rethink components architecture


1. Double negation — !!dangerousData

It’s an easy quick fix that will work and some experiments says that it’s execution time is faster than Boolean(dangerousData). We do not recommend it though.

This solution’s main pitfall is a human factor. Someone in our team could think that it is pointless to do double negation as it goes from true -> false -> true. It may lead to “refactor” that will create potential crashes in the future as this error may not reveal itself at first. My number one principle while coding is readability.


2. Classic conversion — Boolean(dangerousData)

This seems readable but as we mentioned above some say that it is slower in execution time so make our own research and decide if it is OK for our particular case. We can find news that in modern browsers it is optimized. We may also use some transpilers to change it before it goes to final code.


3. Rethink components architecture

Maybe we don’t need as many conditional renders in the component. Every component should be small and have simplified logic as much as it can. We have seen many overly complicated components with nested conditional renders and believe me it’s not something easy to maintain as our code grows.


3.1. Use Element Variable

In simple components sometimes we can use trick from React documentation with if and variable assignment preceding return.

// ...
  let message = <Text>'Hello there!'</Text>
  if (isVillain) {
    message = <Text style={styles.deepVoice}>'General React'oni!'</Text>
  }

  return <View>{message}</View>


3.2. Component Is A Function (IF ELSE In Render)

In class components it would be — render method is a function.

In function, we can call return inside if statement and it will not execute further on. It will have the same result as with Element variable above. We don’t need else here because when condition is satisfied execution will go on, otherwise it will be stopped on first render.

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

const Card = ({ loading, error, title }) => {
  let content

  if (error) {
    content = <Text style={{ fontSize: 24, color: 'red' }}>Error</Text>
  } else if (loading) {
    content = <Text style={{ fontSize: 24, color: 'gray' }}>Loading...</Text>
  } else {
    content = (
      <View>
        <Text style={{ fontSize: 60 }}>{title}</Text>
      </View>
    )
  }

  return <View style={{ padding: 24 }}>{content}</View>
}

export default function App() {
  return (
    <View>
      <Card error={true} />
      <Card loading={true} />
      <Card loading={false} title="Title" />
    </View>
  )
}


3.3 Conditional (Ternary) Operator

Another common case: rendering a different React element for when a prop exists and when it doesn’t. We can accomplish this with the ternary operator. Note that a buttonTitle equal to the empty string, "", won’t render, since the empty string is a falsy value. If we did want it to, we could use buttonTitle === undefined to check for that case.

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

const Card = ({ title, buttonTitle }) => (
  <View>
    <Text style={{ fontSize: 60 }}>{title}</Text>
    {buttonTitle ? <Button title={buttonTitle} /> : null}
  </View>
)

export default function App() {
  return (
    <View>
      <Card title="Title" />
      <Card title="Title with button" buttonTitle="Press me!" />
    </View>
  )
}


Explaining The Array Example Solutions

In Previous example, we show that

dataEntries.length && (
  <View>
    <Text>Visible only when array is not empty</Text>
  </View>
)}

Now we understand that what really happens in above code is returning length to directly into JSX. It happens when length is falsy and it comes from logical operator implementation.

To simplify the example and make things more visible let’s assume that dataEntries.length is 0 and following View with Text component is <Component />. Now we have:

{0 && <Component />}

This expression returns 0 which is converted to string '0' and we can see it as an error in React Native or as an extra character on the web.

The quickest fix possible is to make sure that we don’t depend on falsy value but on boolean false.

Here are multiple fix scenarios:


Double Negation

{!!dataEntries.length && <Component />}


Classic Conversion

{Boolean(dataEntries.length) && <Component />}


Inline Condition

{(dataEntries.length > 0) && <Component />}


Ternary Operator

{dataEntries.length ? <Component /> : null}


Refactor, Rethink, Make It Safe

let coditionalComponent = null

if(dataEntries.length > 0){
	coditionalComponent = <Component />
}

That’s all about in this article.


Conclusion

In this article, We understood how to make conditional rendering safer in react native. We also explained what is happening and how to prevent further mistakes when we use Conditional Rendering .

Thanks for reading ! I hope you enjoyed and learned about Conditional Rendering 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 !!???

Exit mobile version