Performance is quite an abstract word, for a mobile app, there are different parameters to be considered.

For a Lehman,

The app should be working fine, no sluggish navigation or freezed screens, take less memory and CPU and so ultimately less battery usage.

For a developer,

If it has background threads/tasks like location tracking/music player/Bluetooth connectivity then it should be handled carefully so that it eats less battery. On android it should honour the doze mode and on iOS (Let’s not talk on this, it has many things to look at in the name of ‘policies’!)

It is quite obvious for a development team, that while working on React/ReactNative we found many issues just because of fast paced releases every week for every package - including React/ReactNative itself!

To resolve most of the issues we have to manage the ongoing work in parallel with the upgrade/migration task. It is not an easy thing, but it is also necessary to do this on time to time basis so that we can keep our application up to date with the latest versions.

Developers can build a React Native application using a single codebase. The cross-platform capabilities make it the desired framework for mobile app development. A React Native app works with the native components of a device and provides a native look-and-feel.

As compared to other frameworks, React Native application performance is much better. Since there are fewer lines of code, it reduces the lag in the React Native app. And even if it’s there, React Native optimization enables the application to upgrade and perform better.

Based on the above, we derived a few sets of steps to improve the performance and optimizing React Native Apps:-

1. Upgrade all the Packages

It should have all the latest packages, all of them! Let us understand that most of the packages have bug fixes every few weeks in their new versions, including logical improvements. This could automatically improve the performance in some extent.

2. Use better Navigation Libraries

The latest version of ReactNative has improved navigator now, most of the apps using the versions prior to 0.48.x are using the react-native-deprecated-custom-components for a navigator, this can be now replaced with https://facebook.github.io/react-native/docs/navigation.html

3. Use Common State Management – Redux or Flux

It is common for developers to use native component state management if the apps are very small or having a few screens only. This makes sense as there is not much to do for managing states between different screens, but this would be an overkill once the app is growing in size, and then it becomes essential to have common state store so that all different screens (components) can access what is needed easily. I prefer to use Redux!

Now, let’s talk on it in detail!

1. Upgrade React Native to the latest version

Every developer knows that we can simply use the react-native upgrade command, but it would also need us to look at the versions of all the packages/libraries we have used in package.json.

I have gone through the options available and found that the best way to go with is as per the react-native upgrade guide. It suggests using the react-native-git-upgrade package.

The module react-native-git-upgrade provides a one-step operation to upgrade the source files with a minimum of conflicts!

  • Install the react-native-git-upgrade as per react-native upgrade guide.
  • Then execute react-native-git-upgrade 0.55.4, you can change the version here with whichever you want to upgrade to.
  • This will install the new react-native version and change the version in package.json file. It will also create a .patch file inside /tmp dir. Like, /tmp/react-native-git-upgrade/upgrade_0.48.0_0.55.4.patch
  • It may not apply this automatically, so we need to review this and then apply manually by using, git apply –reject –whitespace=fix /tmp/react-native-git-upgrade/upgrade_0.48.0_0.55.4.patch as I was doing upgrade from 0.48.0 to 0.55.4
  • This should now apply all the changes in the .patch file to our codebase.
  • Start react-native start again
  • Run the debug build using react-native run-android to test the new build on Android.

Upgrade dependency packages.

You will face many issues if there are any legacy/deprecated/removed classes from any of the package dependencies, first, we need to fix this to make the build successful.

Like, react-native-camera package has now different classname for the Camera, so that needs to be updated everywhere in the codebase.

Upgrade Android SDK versions.

Change the Android build.gradle file to use the latest versions of SDKs – Like, I have configured this inside my android/build.gradle file,

ext {
compileSdkVersion = 27
targetSdkVersion = 27
buildToolsVersion = "27.0.3"
supportLibVersion = "27.1.1"
googlePlayServicesVersion = "15.0.1"
}

You may face issues for some of the node modules regarding compile SDK versions, never mind, for that we can define the SDK for all subprojects as well!

subprojects {
afterEvaluate {
project ->
if (project.hasProperty("android")) {
android {
compileSdkVersion 27
buildToolsVersion '27.0.3'
}
}
}
}

Now, run the Android build and test the app. Once it runs successfully, you will see may find more issues on different packages which need to be resolved one by one.

Finally, when everything works fine, test your application – manually as well by running your tests – to ensure that everything is working fine.

2. Use better navigation libraries – upgrade to react navigation

It is recommended that if we use the latest version of React Native then we should use the latest React Navigation – Unless we have a specific reason to stick to old!

As you are already using the navigation library, you should have a method like _navigate in your component. This should not take much time for us,

  • The first step could be to change the implementation of this method and try running the app, that way we need changes at a few places.
  • Once it works for one component/screen, we can do the same for all the screens.

3. Use common state management – Redux or Flux

Every small app starts with basic state management at the component level, assuming that we will use Redux when we need it. But, when it grows big there is no time for refactoring and adding Redux, and then the code becomes very complex just because we have to manage states between different components!

It is recommended to use Redux or Flux so that all app state is accessible easily between different components. There are plenty of articles and videos available showing how to use Redux with React/ReactNative.

Some teams also make use of AsyncStorage for small apps, to avoid the complexity of Redux (Yes, it looks complex at a first glance, as it is using functional programming paradigm!). This will allow to read any state anywhere, but then we have to remember to remove specific keys when it’s needed. And this also does not scale to a bigger level, rather this is not the intended use of AsyncStorage.

Upgrade React Native App to Redux

It is very cumbersome to move to Redux from the basic react-native app, so maybe the following steps would help.

  • Setup redux in your application, you can follow the installation guidelines and find some example application article which explains the usage. Use new sample components so that you can test the whole flow – Like, a simple TODO list app would help.
  • Once you have set it up, add example app components in a separate folder – Like, create a new folder inside source dir and install all your sample components there.
  • Create your route for the new component so that you can use it in navigation.
  • Once you are done with this, and your sample screen is working fine with Redux, its now time to touch the real thing! Identify the screen which has very few state management flows.
  • Note down the events/handlers where you are changing the state, Copy that component and give it a similar name- Like, MyComponentOne
  • Change code in there – install Redux, set your containers and reducers for all different events which are updating the state.
  • Once the new version is ready, use that in place of your old component in real code, and see it in action!
  • Now, test that screen properly – It should have the same events and state as the previous version. If you have written any tests, this should be faster!
  • Once you are satisfied with it, you can follow the same process for all your components and, that’s it!

Just one thing to remember, the whole state of any component should now be in redux store and the life cycle of pure react component would be changed accordingly as you would have defined new containers and reducers!

Conclusion

Improving the React Native performance will allow the application to behave properly. React Native implementation in the right IDE is essential to achieve the most our of the application. You need to optimize performance issues in React Native so that the development is seamless and completed within a quick period of time.

There is no silver bullet to it, refactoring is always a continuous process which should be done frequently to keep your app ahead of all issues!

If you are looking for React Native developers, we have a team that can help you. Our 30+ React experts can build high-quality, scalable mobile applications.

Consulting is free – let us help you grow!