Using React Native
Our team develop Android, iOS, and web applications simultaneously using Java, Swift/Objective-C, and Javascript respectively. We are constantly surveying new tools to help speed up our development process. By using React Native, we benefit from maintaining one code base and requiring our engineers to expertise in one programing language for different platform, that is pretty cool.
Unlike PhoneGap and some other tools that advertise the “write once, run everywhere” capabilities, React Native achieves one thing: Using the same language — JavaScript to write applications in different platform. However, in order to adapt to different platforms, there are many situations where you should write different JavaScript code for each platform to optimize the UI experience, such as the animations frame rate.
After exploring further into the framework, we eventually did not apply React Native in our development. I will highlight the key aspects that assisted us to make this decision.
Poor JS render performance
Consider the following code:
This is a simple code which inserts 1000 rows to a React Native ListView component where each row contains an image and a text field, which is a common pattern in many use case of a ListView. We noticed that the React Native ListView requires some time to render new rows; as a result, if the user scrolls really fast, they will experience a sudden stop at the last rendered row as shown below. Hence, it often gives users the impression that they have scrolled to the end of the list; even though, there are actually more rows that have not yet been rendered.
Poor animation performance
In the previous ListView example, if implemented in native application code, we expect the 1000 rows to be scrolled smoothly with no noticeable performance hinderance, a 60 fps. However, when implemented with React Native, we observe that the frame rate can drop to as low as 4 fps in Android.
Consider another simple animation which slide in and fade in an object. The performance of this animation is lower than expected with a frame rate of ~20 fps in an iOS simulator. In many cases our applications will require to perform more complicated animation; therefore, if we decide to use React Native, we may need to consider simplifying or even avoiding some animations to increase user experience.
Lets take a look at another example when expanding and collapsing an item with a spring animation:
When the animation changes the size of the component while the item is expanding or collapsing, the JS rendering thread needs to redraw the component in each frame and then post it to the main thread. There will always be an overhead between the main thread and the JS rendering thread and the animation just makes this gap more obvious. Hence we notice a subtle lag during the animation as shown below:
Handle the details of UI
Using React Native ListView component, you will need to handle features like touch feedback effect, section header style, and click event delegate. In other words, you will not be able to take advantages of the features provided from the native Android RecyclerView and iOS UITableView components. For example, in Android layout XML and iOS storyboard, you can configure the color of the touch feedback effect, set the desired header style, and register a callback for row click event; where as, in React Native, you need to implement that by using TouchableHighlight and create a new style for the header. As a result, it will usually result in an UI with a very different look and feel from the corresponding native Android and iOS UI components.
Keyboard handling is another issue which can be confusing. You need to listen to keyboard events and manually add a spacer below the input box if it is attached to the bottom.
React Native attempts to provide the majority of the platform specific native UI components for developers, for example, TimePickerAndroid and DatePickerIOS. But there are some native UI components which are frequently used (i.e. support library for Android) that are not yet provided. Also there are many open source UI component which can be easily integrated into your native application, but with React Native, you have a more limited source and in most situation you may need to write the UI component by yourself. Therefore, eventually you will lose the convenience in using React Native if your application requires an abundance of custom components.
Loss control of application thread
In native application, you can control your thread, you can cancel tasks or prioritize the threads. In React Native, you loss the control for threads. In our case, we use RxJava and RxSwift extensively, which help us control and post tasks to each thread, and we are used to optimize our app by manipulating those threads.
You can’t eliminate the native code
For example, you need to integrate OAuth for different provider like Facebook, Google, or Twitter. Usually, they only provide SDK for Java or Swift/Objective-C, in this case, you need to write some bride code to make the SDK can be invoked by JavaScript. Another case is Google Play Service, if you are a Android developer, you always has chance to use Google Play Service. In React Native, they don’t bride this for you, so you need to do it by yourself. There are many other situations that you need to write some bride code, even for platform build in components. You can’t expect that your app is developed only by JavaScript.
Conclusion
React Native become a mature framework day by day. However, it has some basic problem and can not be adapted to all types of applications. While we can use some tricks to make the performance closer to native app, like moving animations to native threads and moving processing-intensive tasks to native modules, but that means we need to maintain more code base and the framework does not solve our pain point. We also observe that the Android app of Facebook does not adapt React Native, this indicates that the framework is not production-ready in Android or it has some problem can not be solved in this time. We hope we can see this framework become better and there might be some day we would apply it to our development.
Reference
https://facebook.github.io/react-native/docs/performance.html