Note: This post was originally published on my blog.
UPDATE Feb 17th, 2018: Though not a part of this article, it is worth noting that Facebook changed the licensing of React Native to MIT yesterday. This should come as a relief to many and would certainly increase the library's commercial adoption even further:
React@reactjsWe're relicensing React Native (including Fresco, Metro, and Yoga) under the MIT license to match React. github.com/facebook/react…02:32 AM - 17 Feb 2018
When I was younger (and way out of money), I dreamed of having a slick, brand new electric guitar. Every day, I was checking it out, hoping for the moment, when I would finally be able to afford it and tour the world, like most of my teenage idols. Eventually, the day came, and exalted, I headed home, imagining the endless solos I would finally be able to play on it. Much to my surprise at the time, the guitar sounded incredibly crappy. Moreover, the more I forced myself to play it, the crappier it sounded. Frustrated, I tucked it in a dark corner of my room, where it stood for more than a year. Eventually, I picked it up and we have been best buddies ever since, but by this time, I had realized that the guitar was just a tool. Even the best tool in the world can't help you if you are using it for the wrong job.
Much like my electric guitar, React Native is a well-designed tool. It can serve you well and be your best friend if you use it appropriately. On the other hand, false expectations might lead you to frustration and headaches. I decided to share what I've learned from my brief experience with React Native, and give you my (slightly opinionated) view of how to you use it to your advantage. Perhaps, I would rather start with what it isn't.
React Native is not a Web technology...
...as much as you want to believe it is. Indeed, React Native uses a JavaScript runtime and follows the conventions laid out by React and the JS programming community. You can integrate most of the available JavaScript libraries as part of your apps, and use the same tools for dependency management, testing, and building, which a Web developer might be familiar with. Boy, even StyleSheet can make you feel at home with its CSS-like syntax. However, this is pretty much the point where React Native's resemblance to the Web ends.
Indeed, it is JavaScript, but without the DOM
It is important to note that React Native is not a full-fledged framework, but a library used by, and wrapped inside a native mobile application. There's this notion around RN, perhaps driven by the ease of use of its CLI toolkit, that it can be used for generating cross-platform apps per button click. This is misleading. At the end of the day, React Native is a library which can be integrated into every existing iOS or Android project, and used just like any other library the project depends on. Correct me if I am wrong, but the whole idea about the creation of the library, was to share some of the boilerplate code between the Android and iOS versions of Facebook and Instagram, wasn't it. The fact that one could create entire apps where React Native is sort of the main actor, was more of an afterthought at the time.
This should come to confirm the point that using React Native does not mean you can escape native app development completely. React Native has been created to augment the current state of app development and reduce boilerplate, but it was never meant to replace it. You have to have to have an understanding of the underlying intricacies of the mobile platform you are building for. Move two steps away from a basic To-Do app, and you end up reading about linking C libraries and fixing Gradle bugs. And this is all perfectly fine. Because, this is what a mobile developer does for a living. Did you expect something else? I am sorry to have disappointed you, but that's not what RN will solve for you. At least, it did not for me.
This leads to my second point, which is that the build-it-once-use-it-everywhere approach won't work. You can absolutely share 100% of your React Native codebase between iOS and Android. You should however also keep in mind the fact that your app might end up looking like a poor compromise on any of them, unless you work on the native-level polish. What some developers coming from the Web fail to understand, is that every mobile platform has its intricacies and what works on one platform, may not work on the other and vice versa. While perfectly OK for prototyping an idea and quickly bringing an MVP to the users, when an app project grows, the different platform versions of it, will eventually diverge.
Where React Native Shines
Having emphasized enough on the fact that React Native is not a sort of magic box that makes an app ready out of nothing, but rather, a helper library, let's see what we can use it for. IMHO, the two biggest selling points about integrating React Native into your project, are:
- Cross-platform rapid prototyping of a new app idea (with all the caveats that this brings, of course)
- sharing a balanced subset of your code base between different mobile platforms (let's stick to iOS and Android for now).
- updating your apps more frequently, by downloading the shared JavaScript part directly from a server.
Point one is where most people get excited when they hear about React Native for the first time. Indeed, in spite of everything I have written so far, if this is what you want, yes, RN can help you achieve it. That is, assuming that you are OK with using common UI components present across all platforms, and not care much about performance and native touch and feel. To be honest, for testing out quick and dirty prototypes, why should you? Grab a copy of the RN starter kit and sketch out your idea! I am not going to go into further details on this point, because there are thousands of resources on the Web, illustrating how to make a cross-platform app in less than an hour. This is generally not the point of this article.
For anything other than a prototype, one should assume that active native development is needed, and React Native is primarily used to help reduce the boilerplate between the different platforms. There are two ways to approach integrating React Native into a native app shell. The one is the top-down, where one would design the rough skeleton and workflow of the entire app using RN, but bridge to components developed natively for each platform. This includes bridging both UI (native views, assets, etc) and non-UI components (state managers, network handlers, event bus, concurrency management, persistence, etc). For a large chunk of those, the library already provides reasonable default bridges, for the rest, creating custom bridges between the Js runtime and the native platform is doable, though at the cost of some additional work. The benefit of using React Native as a top-down solution is a shared copy of the entire business logic and app workflow, without compromising on the native look and feel.
The opposite of the top-down approach, would be a bottom-up one. This one would be more appropriate for apps that have been in development for quite a while and already have established native codebases. Imagine a company, willing to introduce customisable widgets inside of its Android and iOS apps. A good example are CTA-s (call-to-actions) and other marketing gimmicks that often need easy customisation, in order to match to the individual user. The cost of developing and maintaining such components natively would increase with time, so sharing their codebase using React Native an embedding inside of native apps may prove to be quite cost-effective, without compromising on the native look and performance. This is for example, how Instagram has been using React Native.
Perhaps the one hidden gem feature that often gets added to the last-but-not-least section (see, even I did it), has in fact little to do with React Native as a library, but with JavaScript's interpretative nature. This allows essentially on-the-fly updates of the shared codebase, and skipping Apple/Google's app store approvals and waiting times. Of course, providing dynamic content is nothing new, and the majority of apps have so far achieve by mixing in a couple of WebViews pulling in actual Web pages from a server. Of course, with React Native one gets the benefit that the rendered content will have a native look and feel, but this does not come without a couple of challenges. To address a few, pulling the JS bundle off of a server, would require actually maintaining one in the first place, guaranteeing low latency, making sure that each new version can actually make use of what the native shell has (version can be an issue), etc.
So, that's it! My relatively opinionated, but hopefully realistic take on React Native. I think it is a great library, certainly one developers should keep in their tool-belts as a Joker card. Every project is different and the decision whether to use React Native for it, should be taken after carefully understanding the project's requirements. Some projects would love to adopt RN ob-board as it is. For others, customization will be needed. For third yet, React Native might be out of question, due to specific platform requirements. Hopefully, my post has helped bring some light to the question. Or, even if it has confused you even more, it has at least opened up some new, more concrete questions, the answers to which will help you make the right choice.
As always, the reader's opinion is very important. Do not hesitate to send me feedback and ask those questions. I will try to shed some further light in follow-up posts. Till the next post!
Top comments (2)
I agree with all your points. As popular as React Native is, I was surprised that it doesn't support some of the native code Apple provides like UITableViewController and UISearchController. I tried to use RN, but got frustrated with the lack of native components. It seems like everyone is just making custom UIViews in RN. I came to the same conclusion that you did, that native development is still necessary and preferred.
Would love to hear your opinion on NativeScript one day :-)