Get better performance of your React Native app

Bansari Patel
Simform Engineering
9 min readJun 28, 2021

We’re in a world where the hybrid application is chosen over the native application. Many frameworks provide the same features like Xamarin, React Native, and Ionic. However, React Native saves your valuable time with its built-in extraordinary features and the amount of code you’ve written in the native framework like Android and IOS.

Starting from the general discussion, the couple of articles believe that the React Native application is slow as a result, they blamed the React Native framework is slow or facing problem regarding performance. Does the actual question arise that is it slow or some piece of code that makes the slower performance of the application? However, there are giant and well-reputed companies like Facebook, Pinterest, Skype which developed their application in the same framework which is “React Native”.

All in all, it can be said that the complex architecture, app start time, image optimization, and a bunch of rendering components negatively impact your application performance. However, you can boost your application by taking care of the below process and follow the code patterns as per below:

  1. Improve app start-up performance:

Let’s first understand what is app start time? App start time is taking the timer in hand, starting the time when the app is started, and ending the timer as soon as all content is drawn on the screen. In simple terms, it's the time from App launch to content drawn. You can minimize your start-up time by taking care of mentioned points.

Find something that takes time to load:

The cool thing about JavaScript and the ability to debug your application is that JavaScript can run on many things and there is a feature called debug javascript remotely on React Native. It actually sends the JavaScript application of React Native to the browser it executes their full application, build the component tree and send the signal to the device and tell to device what needs to render in native code.

Full JavaScript code is rendered in the browser and it means we have full access to development tools that are coming with browsers. For example in Chrome, go to the performance tab then click record and get some sample. It has a very good integration of React Native with a nice flame chart of all the components that are loading and we can see which components are slow or which components are unnecessary. So we can make some assumptions like let’s not consider this component or consider it or let’s optimize that first.

Also, there is another option Systrace with that we can see and trace how the component looks in real devices with React Native.

Moreover, You can use Flipper as its a colleague of android and iOS devices in form of a debugger tool. There are several features which include layout & network inspector, log viewer with clean UI. Furthermore, you can track your functions, methods, and many logical things just to install this plugin. So, measuring performance is an art. But I think these tools are a good start to measure the React Native app.

Fetch Network data in parallel with RN setup

If we’re using Promises which helps to send parallel requests to the server and mapping the result whenever needed. This leads to improve our efficiency of the application and reduce the network request time.

We can use GraphQL as well. It is developed by Facebook and provides open-source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing data, cache the data and increase application performance.

Optimize JavaScript bundle

By default, React Native files will be compiled through one bundle file which tends to follow the outdated pattern but we can implement by splitting the web pack bundle files in various phase of the application.

For instance, we have the 40MB main bundle file to load the application. However, we can scale the files into various bundle files and load whatever we need to load initially when starting up the application.

We can use RAM (Random Access Memory) to perform the mentioned above point in RN to achieve our goal. The main mechanism behind the scene is it can load the files whenever we require the specific features or requirements. Now let’s consider the real-time solution how we can enable this powerful feature in React Native.

Enable RAM Format in iOS:

For enable RAM format for iOS you need to open XCode, select the project, go to

Build Phases, and edit phase Bundle React Native code and images. Before

../node_modules/react-native/scripts/react-native-xcode.sh

you need to add BUNDLE_COMMAND=ram-bundle

export BUNDLE_COMMAND="ram-bundle"
export NODE_BINARY=node
../node_modules/react-native/scripts/react-native-xcode.sh

Enable RAM format in Android:

On Android enable the RAM format by editing your android/app/build.gradle file.

Before the line apply from: ../../node_modules/react-native/react.gradle add or amend the project.ext.react block:

project.ext.react = [
bundleCommand: "ram-bundle",
]

By adding this we are good to go with RAM (Random Access Memory) bundler.

Inline Requires

Let’s say we have very huge components and it does something nasty not only console.log. Now you want to use this component but you know it's a heavy component and it is very slow. You just made the condition that they don’t load that component before I clicked. But you didn’t know import is actually eagerly loading and it’s actually loaded in memory.

Use inline requires which allow you to import files within the function. we define a new variable call let very expensive with undefined and require this module after the click and then it is available for rendering.

we can do these things in the whole application so thanks to metro bundler which allows us to set configuration at the app level.

2. Optimize React code

There is a way to do some smart code that enables your application into beast mode. Now, we are considering a few of the cool techniques which will improve your code and rock into any environment.

Avoid multiple render() calls

Does your component actually need re-rendering again and again? You have to find your answer to this question. Because in React Native application, if your component is rendering again and again then definitely it is impacting your app performance.

Tip: To avoid this we can use ShouldComponentUpdate a method from the component life cycle.

shouldComponentUpdate(nextProps, nextState) {
if (nextProps.isUpdated !== this.props.isUpdated) {
return true;
}
return false;
}

If you don’t want to handle it manually then we can also use PureComponent. This will be applicable for Class Component.

If you want to use it with Functional Component and react hooks then there is react.memo hooks are available to memorize your component value.

Another cool thing available with the npm package is why-did-you-render. The name suggests why-did-you-render which is used to find the reasons behind rendering and help to avoid it. If you made mistake in the wrong rendering it shows logs in the console so, you can fix it.

Note: Make sure why-did-you-render library should NEVER be used in production because it slows down React.

Optimize image

If you are using Images in an efficient way then you are improving your app performance. Because Images consume a large portion of your total app size. Optimize your image is a good deal to handle improve the application. By reducing the size of your graphics, we can reduce the size of an application. The best way to get images of the app’s screens to design the format in the right format, such as PNG or WebP.

Another thing is, right cashing also helps to improve the application. There are many available modules for cashing your images.

Tip: Use a library such as to react-native-cached-image cache and load the images. Here how we can use it.

import { CachedImage } from 'react-native-cached-image'; <CachedImage 
source={{ uri: item.urls }}
/>

Avoid memory leak

As android devices extra processes are running in the background can lead to memory leakage in an application. Avoid that background stuff as much as possible. To avoid memory leaks, avoid using a list view. As list view is depreciated by React Native itself. Instead of a list view try to use a flat list or section list, which can actually improve the list performance.

Reduce Application size

Reducing the size of the application can improve its performance. Now the question is how we can reduce the application size. Most JavaScript application requires the use of native components and third-party library as npm packages which increase the size of an application.

Tip: To reduce the size, use only necessary components, optimize the use of those components and we can also use proguard and reduce the size of graphics. Let’s see how we can set the configuration with android to use proguard.

  • Open the Android studio.
  • In your source folder navigate to android/app open build.gradle file and find below lines.
/**
* Set this to true to create two separate APKs instead of one:
* - An APK that only works on ARM devices
* - An APK that only works on x86 devices
* The advantage is the size of the APK is reduced by about 4MB.
* Upload all the APKs to the Play Store and people will download
* the correct one based on the CPU architecture of their device.
*/
def enableSeparateBuildPerCPUArchitecture = false

/**
* Run Proguard to shrink the Java bytecode in release builds.
*/
def enableProguardInReleaseBuilds = false
  • You don’t need to do much, just set true value to enableSeparateBuildPerCPUArchitecture and enableProguardInReleaseBuilds
/**
* Set this to true to create two separate APKs instead of one:
* - An APK that only works on ARM devices
* - An APK that only works on x86 devices
* The advantage is the size of the APK is reduced by about 4MB.
* Upload all the APKs to the Play Store and people will download
* the correct one based on the CPU architecture of their device.
*/
def enableSeparateBuildPerCPUArchitecture = true

/**
* Run Proguard to shrink the Java bytecode in release builds.
*/
def enableProguardInReleaseBuilds = true
  • enableProguardInReleasebuilds setting this to true actually compress the java byte code in the app file. It’d bring down the size of the app by 50%.
  • enableSeparateBuildPerCPUArchitecture it will provide the benefit of different android architecture, like armebi and x86, the most common one is armebi. Setting this to true will give the output 4 different apk. Each of the .apk files will have a significant reduction in app size.
  • Android App Bundle which is publishing all your compiled and structured code with well-organized resources. Google Play used your app bundle and convert it into a specific and optimized configuration with required resources APK in different compatible devices. So, You’re not going to do stuff like build, sign, and manage APK for various devices.

Note: Android App Bundle should always preferable over enableSeparateBuildPerCPUArchitecture

Native only animation
There are many ways to create animations in a React Native app. One of the most popular ways to do this is to use the Animated library.

Animated useNativeDriver to send animations over the native bridge before animation starts. This helps the animations to execute independently of a blocked JavaScript thread, thus resulting in a smoother experience without dropping many frames.

Tip: To use nativeDriver with the Animated library, you can set its value to true. In the example below, useNativeDriver is used on the rotation of an image our timing function would look like that:

Animated.timing(
this.state.spinValue,
{
toValue: 1,
duration: 3000,
easing: Easing.linear,
useNativeDriver: true
}
).start();

Avoid Scroll view if the list is large
There are few ways to create scrollable lists in React Native. Common ways available in the React Native core are ScrollView and FlatList components.

A ScrollView component is simple to implement. It is used to traverse over a list of a finite number of items using JavaScript’s map() function.

<ScrollView>
{items.map(item => {
return <Item key={item.name.toString()}>
})}
</ScrollView>

The ScrollView component renders all children at once. This is good for when the number of items in a list to render is low. Dealing with a large amount of data can directly impact the performance of the app.

Tip: To deal with large lists of items, React Native provides a component called FlatList. This component ensures that the items are lazy-loaded such that the app does not consume an inconsistent amount of memory.

<FlatList
data={elements}
keyExtractor={item => `${item.name}`}
renderItem={({ item }) => <Item key={item.name.toString()}>}
/>

Final thoughts on uplift your React Native Application Performance

To conclude, the mentioned and facts, if we’re taking care of the coding patterns, in-built features of RN and avoiding the outdated feature and patterns which enabled your application into faster performance and you cannot neglect the “React Native” too early just consider its slower performance.

Thanks for reading this! I hope you’ve learnt new techniques after reading this awesome blog and that will help you out in your code. If you’ve enjoyed and loved this article throw me claps👏 .

--

--