viktor kinko

React Native - application & issues

It's spread meaning that one app development for two platforms takes less time than two apps development while choosing React Native. But it's not. It takes the same or even more because of marketing pitfalls. I'll tell you about some difficulties that I faced for the last months with React Native.
Viktor Kinko
Android Developer
React Native adapts Javascript for mobile development. It uses a number of builders - Metro Bundler that interpritates JS code and gives resources and target system builder. In my case it was gradle for Android. Technically, React Native app has to be run simply. The React Native command run-android turns metro bundler and builds app for each activated Android devices and emulators.
It appears that even this stage has some difficulties. We had permanent Unable to download JS bundle error on our project that means unable translation of bundler to native code. It wasn't launched, as we noticed later. StackOverflow confirmed guesses and showed that bundler has to be run as another thread by react-native start command. It makes possible to restart the bundler only if package.json has changed so the process isn't slowing down.
Package.json is a file of outer modules for applications. On there's an amount of different libraries for RN that expand functionality and make development simple. Many libraries (firebase, for ex) use native functions so they have to be connected with native code. The react-native link <library-name> command is used for this and should set its connections with native code.
Because of the fact that all the libraries are being written at different times they use different SDK versions and require different approach. Sometimes libraries don't match to each other and the last version is experimental so developers advice to downgrade the version to penult. Oftentimes link doesn't set all the required dependencies. So for the Firebase it needs to add a number of additional libraries into native code, connect outer repositories, modify (it's only for Android!). There's a precise manual for Firebase but for other libraries it's rare.
After the set of connections with native code we can build the project and hopefully the library will work. While you build the project it needs to remember that if you get an error you have to be sure that this error is yours, not builder's. For the real sure make some things:
• rmdir node_modules /s /q && npm cache clean - force && npm i

This command will delete the node_modules folder and load it again. This is one of the longest tasks recommended for rarely usage. In terms of some projects node_modules can take many GB and the reset will take a time.
• rmdir android/app/build /s /q

In development process we noticed that unsuccessful build is the result of unable builder's creation or deleting the folder from debug directory. This activity solve the problem of React inability to delete folder. But at the same time files generation for this folder from scratch will take additional time too.
• react-native start - reset-cache

Make Metro Bundler run. This tab has to be opened on debugging. If there's an error so it will be logged here. By error this process ends and you'll need to make it run again.
• react-native run-android

Download the app on device or emulator. Most of the build errors appears here, some of them understandable while others are irrational and debugging by rerunning the process.
Imagine the building process as command sequence for one project (with realm, redux, react-navigation and about 10 more libraries) after firebase launching.
rmdir node_modules /s /q && npm cache clean --force && npm i

react-native start
react-native run-android
>> debug folder is not deleting

react-native run-android
>> error, metro bundler is closed

react-native start
react-native run-android
>> debug folder is not deleting

react-native run-android
>> download sucseed! But metro bundler was closed so JS code is not readable

react-native start
>> after restart pressing it works in the app, it is loading
It takes a long time, isn't it? And it's not one-time process: by the moment written above this procedure needed to be done after each code change. By each new library the project becomes unstable and the process can change for the worse. Debugging is one of the most important functions for developer so in this case its speed slowing down.
In debugging process the debugger has problems not only with launching. Fixing the bugs that occured in test process is difficult too. In RN JS-code is translating into Native-code and obfuscating. If you don't want to get errors like "null pointer exception in zzz.yyy()" you need to use built-in debugger as you can't read exceptions in logcat. With the error debugger shows red death screen with its description for fixing. But here we get difficulties too.
It's ok if the error looks like this:
We see that here is undefined instead of, expected array object in variable, so there's TypeError. It fixes by switching to app.js:14 and checking the variable value before usage.
It's worse if the error looks like this:
Or this:
Images are from Internet but I saw it for myself. Despite the fact it's shown in runtime this error isn't connected with not right code. It can be a consequence of wrong library or some unmatching dependencies
It's worse if the error can't be reproduced in debug. I faced it by attempt to build the app with new version with x64-architecture support for Android. If you download the app with debugger it's ok. But the moment I build the app for tester, it stops working and crashes by database connection. I used console messages that were as React toastAndroid for debugging. This component displays short text by reaching exact code line. Step by step, separating the code in half, we localize function that has an error and get the Object.assign({} method problem - it doesn't work in new React version. Fortunately, we could replace this function by {...item} with saved app functionality but it took about 10 hours to find this error.
Then I made a study. It appears that RN uses different engines for JS-code interpretation in debug and production versions: Chrome JS engine for debugging and JavaScriptCore for work. RN doesn't translate JavaScript into Native-code and interprets in process. The engine works more stable so bugs appear in production. For ex, in this article shown the data formatting process in different situations. Move back to the error: after the updating React Native version web-engine lost Object.assign() support. But the debugging engine is the same.
Seems like the worst situation is app crashing randomly, only in production versions and without RN logs. For ex: after the release version setup the app works some time and stops randomly without any warnings. And the error doesn't appear on all the devices. Eventually, by the finding that firebase crashlytics doesn't send errors, I got crash logs that looked like this:
This text doesn't connect with our application and it wasn't red noted. After I got it I understood that new React version is broken. And the previous one. The official issue tracker has an error Android crashes: signal 11 (SIGSEGV) for two months already, fortunately, two days before it placed decision.
It's ironic but some developers who had a deal with Android Studio were surprised about build/clean project or file/invalidate caches options existence in IDE. It needs for prevention of abnormal gradle behaviour, wrong messages about errors and warnings, synchronization errors. So developers didn't like that they had to do this job for IDE as it has to be done automatically. But they didn't work with React Native. IDE perform all the difficult tasks on background.
All I told you are the particular cases that happened during some past weeks. I don't describe difficulties with application launching by Expo, setting code style in babel/eslint, don't complain JavaScript about its flexibility and I don't tell you how we lost almost all the possibilities for debugging because of redux/realm connection. Taking into account the support and developing difficulties and the fact that process multiplies by 2 for 2 platforms, we decided that React Native isn't profitable for developing. How about you?
Thanks for reading!