The React Native Adventure

coldgrnd
10 min readJun 6, 2018

--

dive into the unknown (image source)

React Native is still a rising star on the mobile app development horizon. It has seen wide adoption even among bigger companies and delivered on the promise of building apps for iOS and android that are indistinguishable from purely native apps. Still, it has it’s quirks and it’s good to be aware of them when faced with the decision on the development platform of a new mobile application.

A couple of month ago I needed to dive into a totally different area than I usually work in: From writing embedded C++ code for very restricted systems to creating a cross-platform react-native app for iOS and android. I had experience with programming in javascript and especially typescript, but had never touched react native (let alone react). So I started out learning about react and all it’s concepts and moved on to react native.

After having spent quite some effort and time with RN development I have gained some insights that might be interesting to other developers considering RN for a real world application. Note that especially my criticism might very well be subjective and might not apply to your situation.

Starting out

As many others I was immediately faced with an overwhelming flood of frameworks, libraries and tools. React, Redux, Flow, Typescript, babel, npm, node, yarn a.s.o. For seasoned javascript devs this might not be such a hurdle but for me it was. The ecosystem is complex. What does not make it easier is the fact that RN itself is a pretty un-opinionated framework and puts some burden on the user to combine the required libraries for the task. While I usually welcome this, it turned out to be quite a lot of work. For everything you need in RN there are multiple valid solutions available. But to everyone not coming from the javascript community: beware that stars on github for javascript projects can be tempting to use as a quality indicator. But very often the equation is wrong and even popular projects are dropped once the owners loose interest. So choosing wisely is quite hard.

Since starting out quickly and with great ease is one of the selling factors to buy into a new framework. RN proponents do everything to make this easy and offer you jump-start kits and application templates. One of the better one comes from infinite.red and is called ignite. That get’s you started quickly but comes at a price: you might not agree with all the choices your starter kit made for you and changing only part of it later can easily become a maintenance nightmare. So my strong advice is to start out with an absolute minimum (i.e. just use react-native init) and keep expanding from there. You will gain valuable insight into how all the parts work together and it will be easier to change bits and pieces.

Think hard if you want to use Expo

Not sure why but somehow the “official” recommended way to start with React Native is to use create-react-native-app that will install all the Expo stuff. While this might seem a quick way to get started (and it its), it forces you down the Expo path which is a bit of a one-way street. Expo adds another layer of abstraction to the already complex RN ecosystem and makes certain tasks difficult to impossible. Most important: using native code is not easily supported with the Expo-way. So as long as you stay on the javascript side of things, Expo makes a lot of sense. Expanding your project into the nativ part will make the road less smooth.

Strive for simplicity first, not features

In RN (as in React itself) the foremost unit of abstraction is a component. This makes it pretty easy to extract parts of functionality from your application into it’s own library. Awesome React Native is a repository that lists a wild variety of modules for your application. It is tempting to go wild and include a lot of those into your app. But this quickly becomes a maintenance nightmare…keeping up with RN versions requires that all the libraries you use also do their share. You might easily end up maintaining multiple forks of your favorite libraries just to keep up with RN itself.

For the most components I initially considered to use it became clear pretty soon that the actual functionality that I needed was not too hard to implement in a simple way. Keeping the dependencies in your package.json small will be a life saver on a later stage in your project.

Know how to clean up

groomed

I don’t know how many times I encountered problems that seemed to have one common solution: try to start over from a clean state.

That does not mean restart you machine…a hint you can find quite often in discussions.

If it wouldn’t be so sad it would be almost funny… Knowing how to restore your system to a working version is hard but crucial! Better to prepare for that in advance so you can avoid painful rebuilds and unreproducable behavior.

But it is actually a non-trivial task. So many things are cached, and often on multiple levels. npm has it’s local registry, watchman needs to be cleaned, gradle works with a cache, xcode another one, android studio keeps some state around a.s.o.

It’s important to be able to get a fresh setup quickly (without reinstalling your computer ;). What worked best for me is to keep a rake task around that does all the cleanup. Here is the one I use:

  • make sure you have a single command ready to clean up (write your own or use something like react-native-surrender)
  • do a lot of small commits so git bisect can work for you
  • test not only on emulators and simulators — test on real devices also!
  • test for both android and iOS since the build can be very involved when you have native modules

Get to know android studio and xcode

Depending on your project you might be able to stay in VS Code or your favorite editor for most of the time…but prepare to jump into the native development IDEs when things get ugly. And there is just no way around it. If you need to release on android and iOS, there are steps that only work in the native IDEs.

Having done some android development in the past android studio is straight forward. gradle can definitely be a hassle, especially if you have to fight with upgrade problems to newer versions. But android studio has come a long way and makes android development relatively pleasant.

xcode on the other hand…wow…just wow. How does apple expect every iOS developer to use this tool? It can be daunting to change even minor configuration options in xcode. And chasing down a linker error is very different then anything you get on a regular make based C++ project. So many things are click-only. Automating anything with your iOS build becomes super painful. But anyway, there is nothing to it, just familiarize yourself with xcode and a bit of objective-c and you will have a much better time.

Make use of a typechecker

As a developer with background in only typed languages, using javascript directly always feels scary. By now most of the fans of untyped languages like javascript have come to appreciate the merits that come with a type-system. The react community mainly uses either facebook’s FLOW type annotations or microsoft’s typescript language.

source

I started out with FLOW (thinking that this is the RN way) but had a lot of issues with it (mainly that the type-checker would not shut up about files that were located in my node_modules folder). Then I turned to typescript and that has gone much more smoothly. Integration with pure-javascript libraries just works. The tooling support especially in VS Code is nothing short of amazing. And the community is very active.

Of course now there is ReasonML which is a damn good typed language (actually it’s just a new syntax for OCaml). But even though there are some amazing developers who managed to code up react native apps with it, it’s still very early and you might end up having to do a lot of extra work to integrate with existing libraries.

Choosing a navigation solution

source

This is one of the major decisions you have to face in your project: what navigation solution do I go with? Unfortunately RN does NOT come with a onboard solution. RN itself recommends either react-navigation, NavigatorIOS or react-native-navigation. The NavigatorIOS solution you can safely skip because it’s iOS only…defeating the reason why you’d go with RN in the first place.

React Navigation is a javascript only solution (so it does not require any native code extensions). It used to be very popular, then got a lot of blame and struggled but now is back on track with lot’s of developers chiming in. The community is strong and the open source project is on a good track.

React Native Navigation is a native based implementation so you get to use the native navigation elements on iOS and android. It is a very performant and popular solution. But the community around it is not as strong as it could be. v2 is a complete rewrite that has been going on forever and there is no indication that it will be finished any time soon (or at all). But it is still under active work which also means the few developers who commit to it do not want to touch v1 anymore and crucial bugs are either not fixed at all or take a very long time.

There are others but I haven’t found any alternative that seemed to be a good fit for the features I needed or it did not get enough attention to really consider it. But for all of the solutions out there it is quite hard to build a stable product that satisfies all your needs and is bug free. I went with RNN v1, switched to React Navigation, went back to RNN v1 and now just stick with it.

Layout and Animation

This is where RN really shines. All layout is done with flexbox. This takes getting used to a little but then is very powerful and fun to work with. With hot code reload this becomes even better since you don’t have to navigate back to the screen you are working on when changing some details. Unfortunately hot code reload didn’t work for me in most cases. I never found out why but it was never such a big issue that I got to the bottom of the root cause.

Animation is cleverly implemented and used in a declarative fashion to keep the interaction between your javascript code and the native drivers at a minimum. The animation API is very intuitive and examples are easily found. Another option is to use Lottie for RN. It is a way to import Adobe After Effects animations and play them directly in RN.

Performance Hotspot: Traffic over the bridge

For most of the time while developing with RN I had no performance problems at all. The execution of javascript code is usually quite fast and you can by all means build apps that are indistinguishable from native only apps. But there is one area that needs special attention: The RN bridge.

source

The bridge communication between the javascript realm and the native realm can easily become a bottleneck. RN uses messages to exchange information between those two. If too many messages are sent in either direction, the app can become unresponsive. This bit me when I was constructing a fairly large list with hundreds of entries. Even with the optimized FlatList and using PureComponents only I could not make the scroll smooth. The bridge would get clogged and jank was very visible.

In the end I settled on a very nice library that uses cell recycling for optimization. Using recyclerlistview I could overcome the problems.

So one good advice when you experience performance problems in RN is always to check your bridge communication.

Build, Test, Deploy and Monitor

Again the best tool I found to help here was done by Microsoft: Visual Studio App Center. It’s a comprehensive suite of tools that make it possible to handle everything you have to do once you have an usable version of your app. You can use it for

  • building your app both for android and iOS (including all code signing procedures)
  • test both at build time and by running on real devices
  • manage releases
  • monitor crashes of your users and view detailed crash reports
  • collect analytics
  • update your app with Codepush (thus avoiding going through the usual release cycle with app-store approval etc.)

Initially I faced some problems with Codepush but microsoft was very quick to respond and fix any issues. App Center is so pleasant to work with that by now I use it also for our android only app-development.

Conclusion

All in all it is fair to say that when building a RN app there are a lot of moving parts under the hood. While most of the times React Native does a great job of smoothing out any bumps, there are some very deep pits that you can still fall into. But the community is friendly and helps you out in most cases.

--

--

coldgrnd

Software developer, interested in concurrency architectures, programming languages, embedded programming and mobile app development.