react-native-realities

Omkar Hande
Prod.IO
Published in
8 min readJul 16, 2018

A summary of our efforts to incorporate React Native into our native apps.

React Native has been creating a buzz in the developer community and we at KNOLSKAPE have arrived at this party too. In this article, I will be covering our journey so far from exploration to the implementation of a small module in React Native.

I’ve divided this article in 5 parts:

  1. Why are we investing our time in React Native?
  2. Our approach to start building an React Native component
  3. What we liked
  4. What we didn’t like
  5. Is React Native the future of mobile development?

Why are we investing our time in React Native?

There are plenty of reasons to explore React Native. For us, these are the top 2 reasons —

1. Building Cross-Functional Teams — We have a good number of JavaScript developers in our Engineering team. Moreover, they are all experienced in Reactjs. Integrating React Native in our native apps enables us to leverage this and make a highly cross-functional team. At the same time, it reduces the dependency on the folks which know primarily native app development which of course are very limited in number compared to React developers.

2. Platform Agnostic Architecture — The ability to achieve more consistent coding practices, design patterns and architecture across platforms (and products) is relatively easier if both web and mobile are on React. As of now, it’s not possible at times to have common practices across platforms especially as native platforms differ a lot from the web.

Our approach to start building an React Native component

We decided to redo the Discussions (Discussion Forums) feature of the Aktivlearn App in React Native. We came up with a design to turn it into Gamified Discussion by adding some gamification elements like stars, badges, and likes.

Here’s the old and new screens side by side

Old Design (Native Android) vs New Design (React Native)

TL;DR — It took us a couple of months

Read on OR skip to the next sections to read about the pros and cons.

Although this was just one screen, we began the integration with the intention of later being able to convert the entire Aktivlearn app into React Native if needed. If you are a React developer, you can think of this like an implementation of just one of the many routes this app will have later.

So we had to make the React app self-sufficient. What does that mean? There should be minimal interactions between React and the Native code, be it for navigation or for network calls. Achieving the latter was a challenging task.

Native App code that interfaces with network and REST APIs of Aktivlearn are abstracted into the Aktivlean Android SDK. SDK is fairly complex in its structure and handles everything from Network Requests, parsing JSON responses, error handling, and network presence.

Since we want to our React app to be self-sufficient, unlike Airbnb and many other adopters of React Native, we completely rebuilt the entire network SDK in JavaScript. This meant that the native side would provide very minimal data to the React Native side for it to initialize — in our case, just the access_token

We used redux and related support libraries for data handling. We used Facebook’s react-navigation for navigating between screens.

In about a less than a month, we were able to achieve this in development mode. However, we struggled for another month or so when we attempted building the release builds for the apps. Next sections will talk about what were the good and the bad parts of this process.

What we liked

  • Declarative Syntax of React — Developer writes what he/she wants to see on the screen rather than describing how to do it. The heavy lifting (rendering or re-rendering efficiently) is left to the library. Although there are many web frameworks which can do that (Angular, Vue etc), there aren’t many for native development. Basically keeping the views in sync with the data is a complex task, and React solves this problem.
  • Access to the massive corpus of JavaScript Libraries — With React Native, you’re essentially coding in JavaScript and hence most of the JavaScript libraries work flawlessly
  • Styling of components using CSS! — As a native mobile developer, I have always dearly missed CSS and moreover a general lack of a mature design language. In an attempt to breach this gap, I did write a library Chameleon which is essentially a CSS parser for Android (not fully exhaustive yet), however, there’s nothing better than being able to use plain CSS directly
  • Developer Experience — Coding in React Native is definitely a breeze with tools like hot-reloading which are available by default in thecreate-react-native-app package provided by Facebook. Interations and incremental builds can be made much faster than in native. Special mention to VSCode for their React Native extensions which help with debugging very well
  • Flux architecture — React is a very natural fit for Flux architecture. This is relatively difficult to achieve in native mobile apps
  • Code once, deploy everywhere — Although, the shortcomings of this are discussed in the next section, this strategy works fairly well. About 97% of our code is platform independent

What we didn’t like

Unfortunately, this list is a bit long..

  1. Maintain all 3 repos instead of 1 — you cannot really be a React Native expert and expect your code to work on both the platforms. You still need to be well aware of either Android or iOS or both native codebases to excel in this. You do need native developers and then you might just consider doing everything natively.
  2. Sometimes the code works only on 1 platform — The “sometimes” being the scary and unpredictable part of this statement. This is something that we started noticing more evidently when we made production builds of the app. Many times, a code that works just fine in iOS would not work in Android at all. Of course, this code was purely React specific and not specific to either of the platforms. As my colleague Rakesh, who worked on the iOS front puts it — “in iOS it is very very forgiving, whereas in android it will not compile, it might crash, it will cry and whine and trouble you for small things.”.
  3. High initial load times — React Native needs a JavaScript runtime to be initialized first to execute. This load time is quite evident sometimes when compared to a pure native app. In our case, however, it is quite an insignificant delay. It might be more evident if the app grows in size or in the low-powered devices
  4. Larger app size — Related to #3, since Android does not come bundled with a JavaScript runtime unlike iOS, the app is bundled with this code and ends up increasing the APK size (of each ABI split) by about 6–8 mb.
  5. Debugging Release builds is tough — If not impossible! Production builds are essentially non-debuggable builds. Many times, the app would function fine in development mode but simply crash in the release build. In our case, after a lot of investigation, we came to know that the problem was with our proguard configuration which was obfuscating the React Native SDKs. Most libraries are proguard — proof in a way and function after obfuscation. This goes to show the lack of maturity in React Native
  6. Cannot create 64-bit builds — We cannot ship a 64-bit APK with React Native. Although our app size is relatively smaller and Google also does not recommend you split your APK, this can be a deal breaker for companies that rely on splitting the APK to reduce the size of the app. You will be forced to withdraw 64-bit exclusive support and instead will have to roll out a giant universal APK for all the 64-bit phones. So with React Native, you cannot harness the power of a 64-bit instruction set processor at this point in time. This is really bad because the number of 64-bit processors are increasing in the market and most high-end phones already function on 64-bit processors
  7. React Native specific libraries are very few — React Native is still new and hence there aren’t many reliable libraries specific to React Native. For instance, we wanted a Rich Text Editor in our Gamified Discussion. We discovered that we had only a couple of options and both did not work properly in Android.
  8. Integration of libraries doesn’t follow community standards — Integration of external libraries often times is extremely cumbersome. Many React Native libraries have a native binding which needs to be included in the native platform. We saw that many such libraries are supplied using a dedicated folder in the npm package itself instead of maven repository or equivalent which is the norm in Android. Sometimes, the integration just fails.
  9. The framework changes too often — React Native library is still in a very primitive stage right now in my opinion, especially for Android. Instructions, documentations, and answers given by people in the StackOverflow community, for example, are often times invalid as the library keeps changing way too often. In our development cycle itself, the library has gone through many changes. Every update, of course, comes with tons bug fixes but tends to sometimes break the older implementations. Backward compatibility does not seem to be Facebook’s forte. Due to all this, finding solutions to problems can sometimes be difficult and the only solution sometimes it to patch the React Native library itself.
  10. List View APIs are good, but not great — Mobile development requires you to use the mobile’s scarce resources efficiently. Having list views which effectively reuse views and perform smoothly is a must. React Native APIs like Flatlist and SectionList don’t seem to be as competent and robust as the native RecyclerView of Android or the UICollectionView of iOS.

Is React Native the future of mobile development?

Let’s talk about the present first. React native is very early stages in my opinion especially when it comes to Android. The unforeseen and unpredictable crashes that happen only in Android and in production builds is something that needs to be fixed for sure.

Also, React Native functions on top of the “Bridge”. The Bridge is a service that connects JavaScript to the native side functions (hence the name, react-native). The Bridge can be thought of as a curator of sorts, that processes all the method calls from JavaScript code and translates it to equivalent methods for the native side. Needless to say, every time a new version of Android comes out, the bridge must also be updated to support it to take advantage of the newly added APIs. As a result, React Native will always stay behind the native platform due to the delay in updating the bridge.

If you are a developer who uses a lot of native code, you will have to use them via the bridge by converting them into modules which are supplied to the JavaScript code. This, of course, can slow down the performance of the app (partly the reason why we rebuilt the SDK within the React app). Not to mention, some developers might not be comfortable with the context switching.

As of now, React Native does not beat native development due to the sheer inability to do a lot of things because the APIs are not exhaustive.

However, the fact that both native platforms seem to be moving to towards scripting languages which are strikingly similar to each other (Kotlin for Android and Swift for iOS) is enough for us to conclude that, in the future, we might just have something like React Native if not React Native itself.

--

--