React Native: the good, the bad and the ugly
I wanted to learn something about React Native, and see if all the (relative) hype around it had some ground. Writing some actual code always helps to make something stick in your head — after reading a book or some tutorials — so I decided to create a quick app as a side project. But it’s hard to justify the extra work hours in the evenings/weekends when you’ve got two little girls waiting for you…so at least it had to be something that I could use with them! And here it is then:
Designed by educators for babies aged 18 months +, Animal Sounds Safari for kids is an interactive, immersive environment for your children to discover the realistic sounds and names of over 60 animals, in different environments (farm, woods, Africa, Asia etc.) and in 10 languages. It’s free, with beautiful illustrations, no ads at all and no text-based menus.
If you download it you’ll see that the app is super simple, but nonetheless it still allowed me to learn a little bit about the overall approach proposed by React Native (change the view’s “state” and have the UI to refresh accordingly), as well as how to manually configure the project for iOS and Android, use custom modules (for text-to-speech, sounds and some UI components), read and write from/to local storage, have localised content, experiment with styles and implement some differences between the iOS and Android versions.
Here are some quick and very partial impressions after this short journey…and with the assumption that I’d need to work on it so much more for some proper feedback…
The good
- Hot reloading (⌘+S in the editor, and the app reloads in a sec on the sim!) is just awesome, and so much better than recompile / wait / run / wait / test / start-over. By the way, this means that your machine doesn’t need to be as powerful as it would otherwise, because you’ll be touching Xcode / Android studio, and compiling / linking much less frequently. Albeit I haven’t tried in practice, it should also mean that after you’ve deployed the iOS app on a physical device, you can just modify the JS (and therefore the app) on a Windows machine, and just see the result on your iPhone or iPad. This is one of the things advertised by Expo in fact, but I don’t see why it shouldn’t work with your own custom app that you build on a Mac machine just for the first run. It might come in handy if you have an iMac at the office/home, but a Win laptop / netbook when you go out.
- RN’s approach is “learn once, write anywhere” rather than “write once, run anywhere”…meaning that you usually have to re-write at least some part of the UI for iOS/Android (as they must actually be different if you want to have a good app that respects the platform’s design guidelines — things like have the FAB, the side drawer and material design on Android…and a bottom tabbar and flatter styles on iOS)…but the language, approach and most frameworks / modules / classes will be the same, so it shouldn’t be too much work (definitely much less than redoing everything from scratch, maybe also having to learn a new language etc.). I first did the iOS app, and then spent a few hours to make it work on Android…so yes, I can see the approach working fine. Oh, and the way you define platform-specific files (having index.ios.js + index.android.js, rather than a single index.js) is super simple. Sharing code is doable and is indeed done as often as possible.
- A side-effect of #2 is that it’s easier to keep your iOS and Android versions pretty much aligned at all times. With the traditional development process, you might launch both platforms at the same time and with feature parity…but then after a short while you realise that one platform is performing better than the other (in terms of downloads, sales, ad revenues, …) and you start cutting costs on the other…which means that one is partially left behind. With RN this would be less of a problem, as the effort to create the Android build after finishing it for iOS (or the other way around of course) is much smaller.
- GitHub has plenty of open source libs/modules can that help you speed up the development. Not as many as native iOS or Android of course, far from it, but I thought it was much worse. Of course, if someone doesn’t exist already you can always create it yourself…or (if you / your team are not skilled in both iOS and Android native dev) maybe hire a freelancer just for that specific (and probably small) job.
- Although I didn’t use the capability, one of the great things of RN is that you can make part of the app as usual, and part with RN. This is how most big apps are employing it in fact, especially if they existed before RN. This is very flexible and a big advantage over Xamarin, for example. Note that this is very different from writing native extensions/module, which both RN and Xamarin can do.
- I like the flexbox layout, how you create the UI with HTML-like code, and the CSS-like styling that’s quick to write, modify and share across components! In Android it’s not so different…but on iOS it is: iOS is much more visual, thanks to Interface Builder, which sometimes however makes it slower rather than typing that 1 line needed to do the same thing. On iOS/IB it’s also more difficult (if possible at all without custom workarounds?!) to share styles across all views. I think I do prefer the RN’s/Android’s approach around this. The Layout lib from Nick Lockwood provides a similar (but partial) approach for regular iOS apps (it creates the UI at runtime from a declarative XML file), but of course it’s a new and small lib from a 3rd party, without someone as big as FB behind it, so…
- I like the overall principle of small reusable components that react to a change in the “state”, which is one of React’s and React Native’s core ideas. “Reactive” apps can also be developed in pure iOS and Android development of course…but it’s easier and more natural with RN, as it’s at the core of the technology, rather than something that’s provided by 3rd party libs and implements in dozens of different ways.
- Splitting the UI code into sub-views that can be customised at initialisation-time with attributes is very easy, and almost a pleasure. (Although I must admit I’d have to refactor my own code, because I didn’t do much around this even if so easy…).
The not-so-good
- Expo and CRNA are great in principle…but not enough even for a simple app like the one I created, as I had to use a few extensions already. As a consequence you need to be at least a bit comfortable with opening / configuring / touching Xcode and Android Studio’s projects and files…especially when things don’t work immediately when you launch the app on the sim to test it (and this will most likely happen at some point).
- Debugging in not at its best, having to rely on Chrome’s debugger for JS, but on Xcode/Android Studio for the native extensions. Jumping forth and back is not convenient.
- The red screen that you get on the device in case of errors in mostly fine and to the point when there’s an actual error on your code…but when there’s a project misconfiguration it often gives you useless hints that you won’t understand, as it shows pieces of JS that are inside the RN’s core libs.
- Practically every tutorial about RN also talks about Redux and N other libs/frameworks…so there’s really a lot to learn. To be honest it’s probably the same with Android and all it’s architecture-related components though (Dagger, RxJava, Retrofit, ButterKnife, Realm, Picasso, Glide etc. etc.).
- JavaScript, as a language, is not as good as Swift, Kotlin or Java. It has improved a lot in the last years of course, and it’s great that it can run everywhere (web frontend, backend, mobile devices, TVs and other smart hardware…a full stack dev’s dream!), but the existence of things like Flow and TypeScript indicate something...
- Similar argument for IDEs: Xcode, Android Studio and Visual Studio are all mature and very stable IDEs that allow you to do plenty without leaving it. Most of the modern smaller editors like Atom are nice and work well enough, but….
Also, maybe I had to install additional plugins, but the intellisense/autocomplete that I got in Atom is nothing in comparison to what I’m used to in proper IDEs. But yes, I realise this is not a React Native’s issue… - It might be because I haven’t used JS professionally for many years…but I have a feeling that mixing the UI with logic, and the fact that there doesn’t seem a de facto standard way for architecting RN apps (not like MVP for Android for example) is a great chance to produce messy code…
- I said above that there are plenty of open source modules for RN, and that’s true. Every time I checked if there was a wrapper for features/tasks I might want to have in my app (not the one linked at the top of this article, but something slightly more complex :), I found something. However, choices were limited, as there were maybe 2 or 3 libs for a particular need — better than nothing, but not great, especially if you can’t be sure (and you can’t) that a lib will keep to be updated, fixed etc. Also, some libs that were developed some time ago might not be perfectly compatible with the RN version that you’re using.
What about the license issue?
Many people are concerned about the RN’s license. Just search on Google. I haven’t studied the topic, as I was more interested in the technical-side of things rather than the legalese. If you intend to use RN for some serious big app it’s worth exploring this more…but for some reasons I’ve got the feeling that this isn’t a real problem for most people. This article written by Dennis Walsh (a patent / IP attorney) is a good read about it.
Just a couple of highlights:
React’s Strong Patent Retaliation Clause is Much Ado About Nothing
and
Facebook wants to make open source software and not be sued — a noble goal. To that end, they can use some harsh and probably unwise clauses. But in this case, for the practical and legal reasons outlined above, it’s hard to find any teeth behind the bite.
My feeling is that even if you ever had to fight against FB, your app would probably be so popular that you might just afford to rewrite it quickly. I don’t know any app which has a super complex proprietary logic baked into the app itself rather than a backend API, anyway…
Is React Native compliant with the Apple’s policy?
There are quite a few horror stories about developers having their RN app rejected by Apple during the review. However, in all the cases I read about, in the end the culprit was some other framework/library, and not RN. Very quickly, Apple doesn’t allow to run dynamically downloaded executable code…but it does allow to execute downloaded scripts run by the build-in WebKit framework or JavaScriptCore (the latter is the case for RN)…so in theory you’re safe even if you download the JS bundle at runtime (to have a over-the-air update/patch) rather than executing a bundle embedded into the app’s package at compile-time.
However…with the OTA approach you can basically completely change not only the look&feel, but also the behaviour of the app…and that is something Apple doesn’t like and doesn’t really want. Rightly so, I might add, because you could basically bypass Apple’s review and still completely change an app’s purpose/content…which is not safe or desirable even from a customer’s point of view. In theory you could turn an app for kids into a porn app…so it’s clear why Apple doesn’t like the idea.
You might be ok with the OTA, but I think you’d be always at risk and it might be safer to just include the already-packaged JS bundle with the app. With current review times often down to a single business day (from the 5–10 days of the past!), and the option of expedite reviews in case of critical bug fixes, there are now less reasons for OTA updates. A “regular” update through the store also gives you the chance to announce what’s new, and show to your users that you do update the app (an app with a “last update date” of a year ago doesn’t look good…).
The OTA approach can however be useful, and not an issue, for Enterprise apps distributed through your own website. (eg: a company might want that its users always run the latest version of the code, without implementing a custom mechanism that checks if there’s a newer build on the company’s intranet to be manually downloaded).
How much does React Native impact the app’s binary size?
Around 5MB, which is definitely reasonable when you consider the size of most other frameworks such as Realm, Facebook or the various analytics SDKs…and what RN is doing for you in return for its size!
And what about the cost on performances?
Negligible as well for a typical app, if you ask me. RN is not like Cordova/PhoneGap or other technologies/frameworks that run inside a webview — a RN app’s UI is 100% native, and the extra cost is just for the execution of the JS bridging, not for the actual rendering on screen. But don’t take my word for it, just download some of the apps built with RN and see for yourself if you could say they are (sometimes partially) RN apps just by looking at the UI or the performances.
Conclusions
I do see many good things in RN, and a lot of potential. It needs to grow and mature, also in terms of tooling and best practices, but it seems like it is enjoyable and productive already. Let’s say I think it’s worth looking at and trying it out to see if it fits your requirements…at the very least if you’re a startup that needs to develop for both iOS and Android at the same time, starting from scratch, and don’t have a lot of people/money/resources.
Things are of course different if you already have well established and big apps with skilled native devs behind them…but even in that case RN might help somewhere (as said previously, a common strategy seem to test it in low-traffic and not-critical sub-sections of an app).
Don’t be afraid to experiment…even if only for the pleasure of learning something new!
P.S.: if you liked this quick summary at all, and you also happen to have little kid(s) waiting for you at home…please don’t be shy: download Animal Sounds Safari for kids from the iOS App Store or Android Play Store, and leave your feedback about it ;)
P.P.S.: I work in the Mobile Team @ ASOS.com (iOS app | Android app), and we’re always looking for good, friendly and talented developers. We use Swift, Kotlin and Java…RN is just my personal experiment at the moment :) If interested, do get in touch with me…