Why is it important?
In previous parts of our guide, we have discussed:
- Reducing the device’s battery usage with UI re-renders
- The best practices around using dedicated higher-ordered React Native components
- Picking external libraries
- Choosing Libraries optimized for mobile
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, it is very likely that you have a dropped frame - the certain operation wasn’t performed causing jitters in the UI.
Certain libraries, such as Animated provide special workarounds - in this case, use NativeDriver - 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 it is important to keep 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 that 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.
Solution: 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 such as 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.
Read more: https://snack.expo.io/7H5S504j3
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.
Read more: https://snack.expo.io/GUFPWl8BD
React Native uses StyleSheet API to pass styles over the bridge most of the time. That API processes your styles and makes sure they’re passed only once over the bridge. During runtime, it substitutes the value of 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.
Benefits: The codebase is faster and easier to maintain
Whether you’re facing any performance challenges right now, it is a good practice 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 section 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.
However, one additional benefit that is worth pointing out is the maintenance.
Note: You can find out more about app maintenance costs on mobile app daily.
In the next article, we are going to give you some practices to achieve animations at 60FPS in your apps.
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. We will be happy to provide a free consultation.