Experience with React Native

March 23, 2018 by Niksa Janjic

As a developer I don’t have much experience with mobile application development nor do I possess the knowledge of native mobile development. Besides Ionic based apps I only had experience building one React Native (RN) application back when RN framework was around version 0.20. I didn’t have real device nor did we publish that application for users/testers to use. As a matter of fact, it wasn’t even hooked to backed, because project was cut short before API was done. Therefore, that application didn’t provide too much experience that I was able to share, but on this date, using RN version of 0.53 and few additional libraries, testing on a real Android and iOS device, building simple scanning app I can share all the difficulties I have come up during the development.

React Native

At the time I started working on a project RN was of version 0.53. From the first time I was working with it, starting the project got a bit simplified as far as I can remember. Installing and starting “Hello world” application, whether it was for iOS or Android and whether it was for simulator or real device is fast and explained decently in RN documentation. Maybe one or two steps could’ve been explained in more detail but even an individual without much experience with mobile development shouldn’t have problems starting up an example app. Even later, building an .apk or deploying an app for iOS testing is covered by documentation. As far as documentation, community and examples existing on a web goes, you will feel satisfied at the beginning. Most of the RN components and APIs that I used were working as expected and as documentation explained it, with just a few small hiccups.

Routing

Back in time, when RN was of version 0.20, I used only routing library that was relatively stable and recommended at that time. It was Aksonov’s react-native-router-flux . At that time it was barely documented and some of the examples in the documentation didn’t work, probably they were outdated. But once I got hang of it and read few articles that tried to implement the same routing library, I was more or less satisfied with it. I thought about using it on this project, but decided that I should look for other options and read few articles to get a better idea what was popular and recommended. One of my colleagues used react-native-navigation and was fairly satisfied with it. Only bigger problem was that it is native implementation of the navigation and it had manual steps to set it up for both operating systems. Also, there isn’t an easy short way of linking dependency using RN CLI link method. I did some research and decided to use react-navigation react-navigation. I mostly decided upon it after reading this article . To be completely honest, I didn’t do enough research as I was trying to start out as soon as possible and play with it. Documentation was not good at that point, because they still didn’t release version 1, but it was enough to get you started. Shortly after I started with the project they released version 1 to which I upgraded. Documentation got better at this point, but I still feel it wasn’t good enough. Especially if you’re using custom router, which you will have to if you want to integrate it with redux . The example of integrating with redux is very simple, not really a real world example, plus, the explanation of why is it setup like that is very scarce. This is the library I had most issues with, that I will delve into later on.

Redux

In most of our applications, we use Redux to manage our state. It provides development tools, documentation is really detailed and there is a bunch of additional libraries that work with it, that we also use. To manage forms we use redux-form , and to persist part of the state to our async storage we use redux-persist . This stack is stable and reliable and I didn’t have any issues that are exclusively tied to any of these libraries.

React Native Camera

For our project we had to use camera to be able to scan barcodes. Because there isn’t any API directly provided from RN, we had to use 3rd party module. I decided to use react-native-camera which I used in my first project to take pictures and browse camera roll. I knew it worked and was expecting it to work again, only this time to be used as barcode reader. Unfortunately, at the time I of my project, this library was in process of switching to new maintainers and migrating from RCTCamera to RNCamera module. Latest stable version was 0.13 which I managed to install and setup after a lot of issues. Following GitHub steps and manual tasks to get it running wasn’t enough. I had to open few issues and do couple of manual fixes. While I was in process of doing that, they released version 1. I couldn’t afford myself to go through the same time consuming process of stabilizing my project for the version 1 so I gave it just one try. After it successfully built, my app started crashing with errors that were in native code, I just decided to revert it back to 0.13 version without any intention of fixing version 1. I can say that once it got up and running I was satisfied with it. Barcode was successfully read both in iOS and Android, you were able to configure which type of barcodes you want to whitelist for which OS and you were able to successfully take pictures when needed. All in all, this library is great unless you have configuration or setup issues.

Issues

Now, I’ll try to list all the issues I have come up with in the course of 4 weeks I’ve spent on this project while building a small, 5 screens app. Application had one login screen, home screen that lists all the possible locations, and 3 screens for scanning product, showing info of the product and manual input of the product when scanning fails. Pretty simple app that shouldn’t have caused so many issues during development.

React Native

RN in development process had couple of frustrating issues. First thing you’ll want to enable is remote debugging so you can debug your code in Chrome development tools. For instance, I used react-native-debugger because it has React inspector and Redux devtools, just what I need. To enable remote debugging you need to open dev tools on device which can get triggered by shaking a device. There you have the option to enable remote debugging and device will automatically connect to remote debugger. Problem with this approach is that on my iPod Touch (6th generation) shaking gesture didn’t work. This approach is a flaw in RN design. There is an issue of people asking for additional ways to open dev tools, but as of now there is no other way. This prevented me from debugging the code for iOS. I tried all the backup solutions proposed in that issue but none of them worked for me. My iPod was updated to latest iOS version at that time, so I couldn’t figure out what could be the issue.

Second major issue that I experienced while developing for Android was when I enabled hot reloading and live reload. These options are refreshing your code in device whenever you make a change in your code. At some point, without any reason, that stopped working. There is an open issue about it but nothing proposed in there helped for me. I tried clearing the cache, running react-native run-android again, reloading device manually, but nothing helped. I tried restarting the PC and starting everything up and still no help. Only when I disabled those 2 options and started reloading my device manually did I get latest code on the device. Metro bundle was still bundling the code in both cases, but for some reason latest code wouldn’t be on the device until those two features were on.

One other issue I had experienced while hot reloading and live reload was enabled was with AsyncStorage. I was initially frustrated and thought that redux-persist doesn’t work with RN and my attention was directed towards debugging that module. After I tried different one I realized that the issue is somewhere else and started suspecting it could be RN’s AsyncStorage. My code would just hand and never resolve a promise when I tried to read/write something to AsyncStorage. Shortly after that I found the open issue about the problem that I had. This issue wasn’t happening all the time, but once I disabled hot reloading and live reload when I stumbled upon previous issue, I also stopped having problems with AsyncStorage.

Hiccups that I mentioned about RN and possibly React were both an issue with iOS. In one example, I used Vibration API provided by RN. Same code was run through Android and iOS, but vibration wouldn’t happen for iOS. Also, I had a ternary operator which would render error message if provided or simple static string, but in some weird way, on iOS it would render both overlapping over each other. I have no logical explanation how could that happen and because I couldn’t debug the code for iOS I couldn’t figure it out.

Lastly, but this is not directly tied to RN, I wanted to use babel-plugin-module-resolver so I can avoid using relative paths, but it didn’t work. After further investigation, it seems that module resolver wasn’t compatible with RN, or at least that is the conclusion I can come up with after reading few issues regarding this problem. I added few more plugins later down the road and they were working, so I assumed it can’t be RN’s fault.

React Navigation

Explaining all the issues that this library caused me would be pointless. I’ll just shortly list few of them. Back button wouldn’t trigger expected React lifecycle methods nor would it trigger their custom focus methods as you would expect (triggering them was really a random thing). Then again, a screen you moved from 5-6 screens ago and then cleared a part of state in redux, would update and throw errors and warnings as it would be missing that data. Sometimes, navigating from one screen to the other causes the app to crash. I feel some things are poorly designed and cause unnecessary complications to make them work as intended, like interaction between screen header and component.

I feel this library, at this state is in poor shape. My decision to use it was a bad one and I regretted it during the development. As of now, there are 105 open issues for this library of which 65 are labeled as bugs. They made a horrible mistake by releasing version 1 of the library that is clearly not in a stable state. There is also an extensive argument in an issue of that library where part of community feels that this routing library simply isn’t a good enough solution to be considered an official routing solution.

On the other hand, maintainers are working really hard and they’re pushing changes daily. You will get some comment on your newly opened issues fairly quick. That gives me some hope that in given time they might fix all the running issues, provide better documentation and more extensive, real world examples of the library. For now, I would recommend anyone to just skip it.

Redux

There’s just one question that I don’t know the exact answer to. With the routing system above we shouldn’t have been using redux. Problem with redux is that it is a persistent state management library. In our case, we have a product page that we show once we scan a barcode. We also clear product data once we move away from product page to scanner page. In that case, previous product page that we moved away from shows PropTypes warnings because it will re-render in background. So, basically, if at any point you are clearing state, for instance during logout, all the screens that you have visited, will throw bunch of PropTypes errors, because they will re-render in the background. I don’t know for sure, but I expect I wouldn’t be having this issue if I didn’t use redux with this routing library, but in the future, I’ll just try different routing lib instead and see how it goes.

React Native Camera

Because this library went into transformation while I was on the project and I had a lot of issues trying to set it up I stayed on the version 0.13. I would recommend using this library because it really works well after you manage to get it up and running. I didn’t find any better solution that works for Android and iOS, whether you want to take pictures, browse camera roll or just scan a barcode. Downside is that there’s a bit of manual setup and there’s a possibility it will not work for you. Latest version was breaking up for me. It would install and build successfully, but the app would crash everytime I would open a camera. Once I get some time I’ll give it a shot once again with the latest possible version at that point.

Conclusion

RN is still like a baby that’s learning to walk, that will eventually master that task. But for now, you are going to have a frustration roller coaster to get things working with any application that is a bit advanced. There’s also not an “official” (largely accepted by community) routing library like there is with web development. At this state I wouldn’t recommend it for anything more serious than just a proof of concept or playground project. But I’ll keep an eye in the future, because it still provides an option to create a mobile application without having to master native mobile development process. After all, it’s still more popular, stable and performant than any other solution that I have found, certainly better than Ionic or Weex (solution using Vue).

If you are interested in innovating and growing your product, let's do it together. Reach out to us today