Why is it important?
In other blog posts based on The Ultimate Guide to React Native Optimization, we touch on the following topics related to improving performance through understanding the React Native implementation details:
- Picking the right external libraries for your app
- Optimizing battery drain with mobile-dedicated libraries
- Animating at 60FPS
- Improving React Native performance with high-order components
Be sure to check them out. Now let’s move to our main topic.
For example, when your bridge is busy processing the data, another call will have to block and wait. If that interaction was related to gestures and animations, you will likely have a dropped frame - the certain operation wasn’t performed causing jitters in the UI.
Certain libraries, such as <rte-code>Animated<rte-code> provide special workarounds. I - in this case, use <rte-code>NativeDriver<rte-code>, - which serializes the animation, passes it once upfront to the native thread, and doesn’t cross the bridge while the animation is running - preventing it from being subject to accidental frame drops while another kind of work is happening.
That’s why keeping the bridge communication efficient and fast.
More traffic flowing over the bridge means less space for other things
Passing more traffic over the bridge means there is less space for other important things that React Native may want to transfer at that time. As a result, your application may become unresponsive to gestures or other interactions while you’re performing native calls.
If you are seeing a degraded UI performance while executing certain native calls over the bridge or seeing substantial CPU consumption, you should take a closer look at what you are doing with the external libraries. It is very likely that there is more being transferred than it should be.
Use the right amount of abstraction on the JS side – validate and check types ahead of time
When building a native module, it is tempting to proxy the call immediately to the native side and let it do the rest. However, there are cases like invalid arguments, that end up causing an unnecessary round-trip over the bridge only to learn that we didn’t provide the correct set of arguments.
Bypassing arguments to native module
That operation will perform without any issues, even though we haven’t passed the complete list of arguments needed for it to work. The error will arrive in the next tick when the native side processes the call and receives an exception from the native module.
In such a simple scenario, you have lost a bit of time waiting for the exception that you could’ve checked for beforehand.
Using native module with arguments validation
To put this into better perspective, let’s take a closer look at styling within React Native apps.
The easiest way to style a component is to pass it an object with styles. While it works, you will not see it happening too much. It is generally considered an anti-pattern, unless you’re dealing with dynamic values, such as changing the style of the component based on the state.
React Native uses StyleSheet API to pass styles over the bridge most of the time. That API processes your styles and ensure they’re passed only once over the bridge. During runtime, it substitutes the value of the style prop with a numeric unique identifier that corresponds to the cached style on the native side.
As a result, rather than sending a large array of objects every time React Native is to re-render its UI, the bridge has to now deal with an array of numbers, which is much easier to process and transfer.
Whether you’re facing any performance challenges right now, it is smart to implement a set of best practices around native modules as the benefits are not just about the speed but also the user experience.
Sure, keeping the right amount of the traffic flowing over the bridge will eventually contribute to your application performing better and working smoothly. As you can see, certain techniques mentioned in this article are already being actively used inside React Native to provide you a satisfactory performance out of the box. Being aware of them will help you create applications that perform better under heavy load.
One additional benefit that is worth pointing out is the maintenance.
Need help with performance optimization?
We are the official Facebook partners on React Native. We’ve been working on React Native projects for over 5 years, delivering high-quality solutions for our clients and contributing greatly to the React Native ecosystem. Our Open Source projects help thousands of developers to cope with their challenges and make their work easier every day. Contact us if you need help with cross-platform or React Native development.