React Native Optimization

Amir Diafi
4 min readFeb 26, 2022

make your React Native App even faster.

Photo by Magda Ehlers from Pexels

A compelling reason for using React Native instead of WebView-based tools is to achieve 60 frames per second and a native look and feel to your apps.

React Native is a great tool to build Cross-Platform applications; But truly it is bad sometimes, especially when you build a big one with some animations and a lot of screens, that will make your application in areal trouble if you do not enhance the performance; So today in this article we’ll talk about ways to make your React Native App faster.

Firstly, Let’s talk about the unnecessary rendering of some screens while the user is on some screen (example: the user is on the chat screen that it is included in the chat stack with some other screens), react will re-render the other screens if something happens like new notification, and change the store as well, and that’s not a good behavior for good performance, we should avoid unnecessary re-renders of parts of the app that are not visible to the user at a given moment.

To do this there is a cool library called React Freeze from the coolest people from software-mansion

just install it by running:

npm install react-freeze --save

Wrap some components you want to freeze and pass freeze option to control whether renders in that components should be suspended:

function SomeComponent({ shouldSuspendRendering }) {
return (
<Freeze freeze={shouldSuspendRendering}>
<MyOtherComponent />
</Freeze>
);
}

To use in react native You have to be using React Native 0.64 or higher and react-navigation 5.x or 6.x.

make sure also you have the react-native-screens@3.9.0
if you haven’t just run

npm update react-native-screens@3.9.0

If you’re building for ios you also need to run

pod install — project-directory=ios

In order to do freeze your screen, add the following snippet (along with the import) to the main file of your application:

import { enableFreeze } from “react-native-screens”;enableFreeze(true);

Secondary, Frames, Why you should be careful about detecting your app’s frames?.

iOS devices display 60 frames per second, which gives you and the UI system about 16.67ms to do all of the work needed to generate the static image (frame) that the user will see on the screen for that interval. If you are unable to do the work necessary to generate that frame within the allotted 16.67ms, then you will “drop a frame” and the UI will appear unresponsive.

There is a Javascript thread, this is where your React application lives, API calls are made, touch events are processed, etc… and it is an expensive thread.

And there is the UI frame rate (main thread — Native one), and it is the fast thread.

Be careful when you use the Animation API and use the main thread, just by adding the option

{ useNativeDriver: true​ }

The third way is to remove the logs as you can, these statements can cause a big bottleneck in the JavaScript thread.

You can also install this package to do all the work for you:

npm i babel-plugin-transform-remove-console — save-dev

and then edit the .babelrc file under your project directory like this:

{
“env”: {
“production”: {
“plugins”: [“transform-remove-console”]
}
}
}

This will automatically remove all console.* calls in the release (production) versions of your project.

My TouchableX view isn’t very responsive?

Sometimes, if we do an action in the same frame that we are adjusting the opacity or highlight of a component that is responding to a touch, we won’t see that effect until after the onPress function has returned. If onPress does a setState that results in a lot of work and a few frames dropped, this may occur. A solution to this is to wrap any action inside of your onPress handler in requestAnimationFrame:

handleOnPress() {
requestAnimationFrame(() => {
this.doExpensiveAction();
});
}

Finally, Enabling Hermes Engine to improve the start-up time (that’s a real issue in React Native Apps), decreased memory usage, and smaller app size.

Hermes engine was provided just for Android apps, now React Native team has added this feature on iOS as well.

To Enabling Hermes

  1. Android:

Edit your android/app/build.gradle file and make the change illustrated below:

project.ext.react = [
entryFile: "index.js",
- enableHermes: false // clean and rebuild if changing
+ enableHermes: true // clean and rebuild if changing
]

Next, if you’ve already built your app at least once, clean the build:

cd android && ./gradlew clean

That’s it! You should now be able to develop and deploy your app as usual:

npx react-native run-android

2. iOS

Since React Native 0.64, Hermes also runs on iOS. To enable Hermes for iOS, edit your ios/Podfile file and make the change illustrated below:

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
)

Next, install the Hermes pods:

cd ios && pod install or npx pod-install

That’s it! You should now be able to develop and deploy your app as usual:

npx react-native run-ios

And voila you should feel your application faster now.

Thanks.

Follow me on Twitter: https://twitter.com/diafi_amir
Contact me on Linkedin: https://www.linkedin.com/in/amirdiafi/

--

--