Mon, Mar 27, 2017
I just came across an old answer I posted in Quora on August 2015 about the future of iOS development. Roughly a year and a half has passed, and things haven't changed too much to be fair. One of the key points I mentioned in my answer is the ability to speed up the "try" cycle so you don't have to wait to see your changes. My original bet was on the Apple side, but so far it hasn't happened.
For the past couple of weeks I have been diving into the world of modern web development, and one of the most interesting topics for me was React. How the separation of concerns is drawn and how quickly I got a non-trivial app running really called my attention. Everything was pretty smooth, even for someone like me with almost no knowledge of the modern Javascript environment and its pitfalls.
I already knew about the existence of React Native but the fact that you need to write Javascript and ship a JS engine as part of your app kept me for really giving it a chance. Now, after I learned some React, I decided to try out how the dev flow feels in a mobile environment so I did what anybody would do in my place: write a TODO app.
The app has some simple animations and some native-side code to hold the list of todos. My intention was to explore how the communication with some custom native-side components worked and find out how hard it is to get a simple UI that feels native. The main question I wanted to answer was if React Native does in fact bring the web development cycle to the mobile world.
I wrote a native component for iOS and another one for Android. Both do the same, handle the list of todos (add, delete and toggle the "complete" state). The original intention was to handle the list in the user's calendar, so adding a todo should add a reminder to the user's calendar, but I ended up verifying my hypothesis about React Native way before reaching that feature so it fell out of scope.
Next, I list some of the things I found particularly grateful to have during the development.
Coming from iOS I was amazed with Flexbox and how well it played in the mobile environment. I was able to perform simple translation + resize animations without any code on both platforms and spent very little time thinking about layout. This is a big contrast to how this is handled in native iOS (fixed position + autoresizing mask + auto layout + view stacks).
Promises are part of the standard language and are available out of the box. This is particularly useful given that all the communication with the native components is asynchronous. Also, the preferred method to perform http network requests is with Javascript Fetch method (think of it as the new XMLHttpRequest
), that also use promises.
Promises also play smoothly with some of the new features included in the ES2017 version of ECMAScript (aka Javascript) included by default in all React Native projects like:
async
and await
function decoratorslet [a, b] = someArray
Also, if you bootstrap your project with react-native init
tool you get a default Flow config file for free. Flow is a tool that allows you to add type annotations to Javascript and use the flow-bin
tool to check that your types match. This fits nicely with how React allows you to specify types for the properties of your components and make your React code type safe which is great.
React Native runtime supports a nomenclature to specify which definition of a component it should use based on the platform where the code is running. So if you have a NiceWidget
component that looks different depending on the current platform, you can split the logic in two files NiceWidget.ios.js
and NiceWidget.android.js
and at the point of use make reference to the name without any extension: let component = require('./NiceWidget')
I really can't find too many downsides in the technology for now, but I'm pretty sure this is a clear signal of my lake of experience. Anyway, these are some observations that can be seen as downsides but really depends of the context.
You need to be clear about what React Native is and when it's the right choice. Because it's running a Javascript engine it is clear that you are taking a considerable performance penalty, so if you need all the device's power, using React Native doesn't seem the right choice.
You also have to be careful about what packages you install and watch the versions of everything. React ecosystem moves fast and things get old quickly, so you need to take the versioning of everything in your project with caution. Also moving to a new version of React Native could be complicated so reserve some time for that if you need to do it.
As I understand, the feature set for Android is different that the one for iOS. This means that new things are available for iOS before they are for Android. This time, I didn't hit that particular wall though. What I found is that writing native components for Android is much more cumbersome than for iOS. Part of this is because of the weak type system between Objective-C and Javascript that allows things like sending NSDictionary
instances over the bridge to the React Javascript code without any further treatment.
For Android you need to construct a special data type WritableNativeMap
that holds the type information for each value you put in. Also declaring a native component needs much more effort than for iOS. In iOS you just add a class to the project; for Android you need to create a class that implements the ReactPackage
protocol to load your new component and then pass an instance of that class to your main activity.
For my TODO app I picked Objective-C (ObjC for short) over Swift for a variety of reasons. First and foremost, React Native for iOS is written in ObjC and relies on the ObjC runtime to load and interact with the native components you write. For a Swift class that means you have to:
@objc
Also I used react-native init
command to bootstrap my project and for iOS it generated an ObjC project so I was half way into ObjC from the very beginning. All the documentation and examples in the React Native site specific to iOS assume you are using ObjC, they don't even mention Swift.
Given all the above, you have to think twice about using Swift with React Native. I have been working on Swift for a couple of years and in ObjC for a couple more, so for me it isn't worth the effort. Maybe if the native component needed more code I would consider it.
Regardless of the fact that React and React Native are the same framework, there are some difference between them. First the components are not the same, you can't use div
, input
or p
tags because you are no longer rendering to the DOM. That means that if you are an experienced React developer you still need to learn what components are available and, more importantly, how a screen should be split and what components you put in. That's pure mobile development experience and knowledge of the underlaying SDK. There are some generic components that work for both platforms but there are cases in which the proposed UI doesn't match one of the platforms, so you need to use a platform-specific component.
By far where React Native shines is in bringing the web workflow to the mobile development without ending with a full web app running on your phone. During the development of my TODO app, I was running the simulators for Android and iOS at the same time and just needed to hit a refresh shortcut to see my changes. No need for any IDE or compile - deploy - run cycle. That single feature by itself adds enough value to at least give React Native a try.
If on top of that you add the multi-platform capabilities and the fact that any web developer with minimal experience in React (I believe at least 90% of the web developers meet that condition) can write native-feeling mobile apps with little training, I think that React Native can become the way to go for almost any mobile app, at least at the early stage.
© 2024. All rights reserved.