How to improve the performance of a React Native App?
Tags: react, reactnative, performance, javascript
Published: 2021-06-28 03:13:21

See how you will boost your [react native app](https://www.kpiteng.com/services/mobile-app-development/react-native-app-development/) performance, improve start-up time, decrease bundle size & memory usage.

#####Key Points -
* Hermes
* Avoid re-rendering using useMemo
* Cache Images
* Use nativeDriver with Animated Library
* State Management With Redux/MobX/Apollo
* Remove Console Log
* Optimize Android App Size

###1. Hermes
[Hermes](https://reactnative.dev/docs/hermes) is an open-source JavaScript engine optimized for React Native. Hermes integration helps to improve start-up time, decreased memory usage, and smaller app size.

With Hermes your app will start at 2x speed, memory usage will decrease to 30%, android app bundle size decreased 30%, iOS Application performance will boost.

Let’s see how to integrate [Hermes](https://hermesengine.dev/). Hermes supports iOS support after the 0.64 version. So make sure you upgrade your app using [React Native Upgrade Helper](https://react-native-community.github.io/upgrade-helper/?from=0.59.0).

####Enabling Hermes -

**Android -**
Add following code line In android/app/build.gradle
```
project.ext.react = [
  entryFile: "index.js",
-     enableHermes: false  // clean and rebuild if changing
+     enableHermes: true  // clean and rebuild if changing
]
```
If you're using ProGuard, add following rules in proguard-rules.pro :
```
-keep class com.facebook.hermes.unicode.** { *; }
-keep class com.facebook.jni.** { *; }
```
Clean the build
```
cd android && ./gradlew clean
```
**iOS -**
Edit ios/Podfile file with below code lines -
```
use_react_native!(
  :path => config[:reactNativePath],
  # to enable hermes on iOS, change false to true and then install pods
-    :hermes_enabled => false
+    :hermes_enabled => true
)
```
Install the Hermes pod
```
cd ios && pod install
```
That’s it, Now create your iOS & Android build and see application start-up speed, memory usage, and specially bundle size.

###2. Avoid re-rendering using useMemo
[useMemo hooks](https://www.kpiteng.com/blogs/react-hooks) helps developers to avoid re-rendering of child components to improve the performance of react application. useMemo is used to handle memoization, meaning if any component receives the same props more than once, it will use previously cached props and render the JSX view and return component.

In the sample below I have taken FlatList and Button. First time Flatlist renders perfectly. Now when user pressed button new setCount will update state variable and whole component getting reloaded with FlatList even no values updated in Array. To avoid this I have wrapped FlatListItem (UseMemoListItem) with useMemo, so useMemo checks if any change in props then only it will render the JSX else it will return render & return the view previous props.

```
const technology = [
  { name: 'React Native' },
  { name: 'React.js' },
  { name: 'Next.js' },
 ];
 const [arrTechnology, setArrTechnology] = useState(technology);
 const [count, setCount] = useState(0);

 function UseMemoListItem({item, onChange, arrTechnology}) {
  return useMemo(() => {
    return (
      <View style={Styles.container}>
        <Text>{item.name}</Text>
      </View>
    );
  }, [item.status]);
 }
  
  return (
    <View style={Styles.container}>
      <Button title='Increment' onPress={() => setCount(count + 1)} />
      <FlatList
        data={arrTechnology}
        keyExtractor={(item) => String(item.name)}
        renderItem={({item, index}) => (
          <UseMemoListItem
            item={item}
          />
        )}
        ItemSeparatorComponent={() => <UseMemoListItemSeprator />}
        showsVerticalScrollIndicator={false}
      />
    </View>
  );
```

###3. Cache Images
React Native Image component allow developers to display Images in application, still there is few issues like -

* Rendering number of Image (Product List - ECommerce Application)
* Low performance in Caching Image Loading
* Image flickering

To solve this issue React Native support in-build caching for [iOS](https://reactnative.dev/docs/images#cache-control-ios-only) by enabling following lines of code.
```
<Image
  source={{
    uri: 'https://example.com/image.png',
    cache: 'only-if-cached'
  }}
  style={{ width: 400, height: 400 }}
/>
```

But, what to do for Android, there is a popular third-party library named - [react-native-fast-image](https://github.com/DylanVann/react-native-fast-image) which will work perfect for iOS & Android. Using Fast Image you can give quick image rendering, caching mechanism and many more to application users.

```
import FastImage from 'react-native-fast-image'

const YourImage = () => (
    <FastImage
        style={{ width: 200, height: 200 }}
        source={{
            uri: 'https://yourimageurl.com/image.png',
            headers: { Authorization: 'token' },
            priority: FastImage.priority.normal,
        }}
        resizeMode={FastImage.resizeMode.contain}
    />
)
```

###4. Use nativeDriver with Animated Library
We are using animations in our Application, but sometimes it will not run smoothly as expected which impacts application render performance. To avoid flicker and run smooth animation, [useNativeDriver](https://reactnative.dev/docs/animated) which send animation to native bridge before animation start on component. This helps animations to be executed on separate javascript instance, which resulting in smoother animation.

It’s very simple to integration - **useNativeDriver: true**

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

###5. State Management With Redux/MobX/Apollo
Many times it is required to manage data locally means caching data which shows immediately to the user without interruption whenever the user comes back to the application. We are using AsyncStorage, Local Database Storage to store data and when the user comes back next time/ open application next time we are fetching data and keeping it in Global variables to access anywhere in the application.

To manage this in various screens and storing data into various arrays, object Prefer popular State Management Library like Redux, Redux Rematch, [MobX](https://www.kpiteng.com/blogs/mobx-state-tree) and [Apollo](https://www.kpiteng.com/blogs/react-native-apollo-graphql). These library will storage | mange | retrieve data for you and you can easily access throughout the app without any interruption.

###6. Remove Console Log
All we are using **console.log('Hello KPITENG!')** to debug applications. While deploying an application if we keep console.log() then it will create performance issues due to javascript thread.

To remove console.log in Production, following simple installation and setup.

```
npm install babel-plugin-transform-remove-console
```

Now, modify the .babelrc file to remove the console statements, as shown below:

```
{
  "env": {
    "production": {
      "plugins": ["transform-remove-console"]
    }
  }
}
```

###7. Optimize Android App Size
React Native Android apps contain -

* Resources such as images, fonts, etc.
* Four different binaries compiled for different CPU architectures
* Javascript bundle with business logic
* Other in-built files

While you are building an app this will combine all these and create a binary for you. To [optimize binary size Android build](https://reactnative.dev/docs/signed-apk-android#enabling-proguard-to-reduce-the-size-of-the-apk-optional) in React Native by adding below line

Update following line in android/app/build.gradle

```
def enableProguardInReleaseBuilds = true
```

If you want to extract four different binary according your CPU architecture then,

```
def enableSeparateBuildPerCPUArchitecture = true
```

**Thanks for reading Blog!**

KPITENG | DIGITAL TRANSFORMATION
www.kpiteng.com/blogs | hello@kpiteng.com
Connect | Follow Us On - [Linkedin](https://www.linkedin.com/company/kpiteng/) | [Facebook](https://www.facebook.com/kpiteng) | [Instagram] (https://www.instagram.com/kpiteng)