An iOS Developer on React Native
When I first caught wind of React Native, I thought of it as nothing more than a way for web developers to dip their feet into native mobile apps. The premise that JavaScript developers could write an iPhone app in JavaScript was definitely something that I thought was really cool, but I quickly shrugged off the idea of using it myself. After all, I had already been doing native iOS development as a hobby for many years, and professionally with Chalk + Chisel (formally Bolster) for almost two years at that point.
I had already made dozens of iOS apps — good apps that I was proud of. Apps built in Xcode and written in Objective-C, because that’s the way it’s always been. That’s what Apple gave us to make iOS apps, so that’s what I and every other developer used. Then, two years ago when Apple released the Swift programming language, I didn’t hesitate to try it out.
It was still in Xcode, and it was still (obviously) Apple-approved for developing iOS apps, so I dove right in and picked it up pretty — ahem — swiftly. I was content in my Apple ecosystem bubble. React Native seemed like a fun little experiment, but in my mind any real native app would still need to be written the real native way. It seemed like a waste of time for me to not only learn JavaScript (I had no experience), but an entirely new way of building apps when I was already beginning to master building them the “real” way.
Fast-forward a couple of months, and I’m confident enough to say I may never write an iOS app in Objective-C or Swift again.
We received a new mobile app project and I reviewed the requirements and designs. Just as I was about to click that beautiful blue Xcode icon to start a new project, our Interactive Director, Adam, walks over and says, “let’s do this one in React Native”.
He explained that part of our contract for this project was to have a clear path going forward to make this app available for Android as well . And although React Native was not yet available for Android, we knew Facebook was actively working on it. Theoretically, if we built the app in React Native for iOS, many parts of it would “just work” on Android by the time it was released.
Well, I wasn’t happy. I felt as if I was at the peak of my iOS development ability and was being asked to throw it all away. I doubted my own abilities to deliver a quality product on time given the inevitable learning curve. But even more than that, I doubted React Native in itself being capable of producing a quality product. Looking back, I don’t even think that doubt was unjustified. At the time, React Native had just come out as a beta. The documentation was lacking, the amount of open sourced React Native libraries and components was minuscule, and example code or Stack Overflow posts for reference were almost nonexistent.
I begrudgingly gave it a shot. But going in with my closed-mind attitude only did more harm. My first hurdle was learning Flexbox, React Native’s way of doing UI layout. Coming from the land of interface builder, laying out UI completely in code frustrated me beyond belief. I struggled to build even the most simple of views.
But it wasn’t just UI — everything was different. That was the biggest point of contention for me.
Every time I got stuck or didn’t understand something, I would tell myself “I could do this in 5 seconds in Objective-C”. Every time I would discover a bug in React Native (and there were a good number), I would think, “this bug doesn’t exist in Objective-C, why am I fighting with it?”
For a solid two weeks I was miserable at work. I had gone from feeling like an expert iOS developer to feeling like I’d never written a line of code in my life. It was defeating, until I took a weekend to clear my head. I took a step back and recognized that Adam had done a lot of research on React Native. I had to trust him as our Interactive Director to not be leading me down a bad path. I vowed to go into work Monday, put my head down, pretend Objective-C and Swift don’t even exist, and figure this thing out.
Learning to Love React
A few weeks ago, we submitted our first React Native app to the App Store. I’m extremely proud of how the app turned out, and I can’t wait to write our next one. In just a little over a month, consider me fully aboard the React Native train. What changed my mind?
The React Paradigm
In React, every piece of UI that is or ever will be lives in the render() method, and is controlled with “state”. Your render() method defines how the UI should look for each state, and upon calling setState(), React figures out what needs to change and does it for you. Imagine a simple view with a label that says “Hello World” and a button. Each click of the button needs to change the label between “Hello World” and “Goodbye World”. In Objective-C, I would need some ugly if statement in my button handler like
if ([label.text isEqual:@”Hello World”]) { label.text = @”Goodbye World”; } else { label.text = @”Hello World”; }
It works fine, but that UI code is completely disjointed from where I created the label in the first place (which could be in code or in interface builder). In React, we would define a buttonClicked bool in our state, our label in render() would look something like:
<Text> {this.state.buttonClicked ? ‘Hello World’ : ‘Goodbye World’}</Text>
and our button handler is as simple as:
this.setState({buttonClicked: !this.state.buttonClicked});
All the view code is in one place, and state controls all. This makes comprehending and debugging the code so much easier.
Flexbox
The UI layout tool that I hated so much at first is now one of my favorite things about React Native. I will admit that it is tough to grasp at first, but once you do it makes building UI’s for the variety of different screen sizes extremely fast and easy. I had become addicted to the visual aids of Interface Builder in Xcode. Autolayout now seems overly complex compared to Flexbox. The CSS-esque styling that Flexbox uses makes style reuse as easy as copy paste. And the best part of all allows you to tweak style values to perfection in no time…
Live/Hot Reload
That’s right. Seeing what your button would look like moved over 5 more pixels to the right is as easy as Command+S. React Native can be configured to automatically re-render the current view in the iPhone Simulator without rebuilding the Xcode project. This is huge because not only do you save time by not rebuilding, but you could be working on a view that is nested deep within the app and tweak the UI without having to navigate all the way back to that screen.
Android
It’s still not out yet, but it’s coming — and it’s going to be amazing. I was hesitant about React Native at first because I already liked doing native iOS development. I didn’t have any complaints about it. But I’ve also done native Android development, and it’s not great. React Native will be very welcome on Android, and I am counting down the days until it’s here. This will revolutionize mobile app development by being able to deploy to 2 platforms with 1 code base.
[Update: Since the publication of this post, React Native for Android has been released. To learn more about it, visit: https://facebook.github.io/react-native/]
Retrospective
Missing Xcode
I still miss Xcode, or really just an IDE in general. I’ve worked toward a pretty good React Native development setup, but it wasn’t easy. Sublime Text and a bunch of plugins later and I have good syntax highlighting and linting. Sublime can autocomplete based off other variables and things within the same file, but is lacking some of the robustness of Xcode’s autocomplete. I still have to leave the React documentation up all the time to use as a reference.
Little things like typing React.PropTypes.f and having the IDE not tell me whether I’m looking for ‘func’ or ‘function’ can be bothersome. I also miss Xcode’s version editor — which allowed me to compare a file side-by-side with that file at my last git commit and even undo specific changes on a per line basis. I realize a third party program could help me accomplish this, but one of the great things about IDEs is the all-in-one package.
To run a React Native project, I need to launch my terminal to start the npm packager, Chrome for the debugger, Sublime to edit my code, and ultimately Xcode to run the project and start the simulator. These are all minor complaints in the grand scheme of things, but still a con for me when it comes to React Native. I have high hopes that Nuclide (Facebook’s IDE) will alleviate some or all of these cons.
Bridging
Facebook hasn’t and isn’t going to port every API from iOS to React Native, so for the missing pieces they’ve provided a way to “bridge” things over to JavaScript. Again, when I first got into React Native, the documentation on this was really bad. Every time I realized I needed to bridge something, I wanted to give up on React Native altogether because naturally those things already work in Objective-C. But once they explained the bridging process in more detail, and provided good examples, it wasn’t as intimidating. It still is a hassle, but eventually I could see every bridge imaginable being made open source and available on npm. In fact, most iOS APIs already are.
Bugs, Documentation, Open Source Community
Most, if not all, of my initial complaints about React Native wouldn’t even exist if I started learning it today. Bugs are fixed daily, and new releases seem to pop up every week or so. The documentation still needs work, but has greatly improved. Facebook and the open source community in general are clearly very serious about developing this framework. It’s nice to see people actively engaged in React Native issues on GitHub and questions on Stack Overflow. If you are an iOS developer considering playing with React Native, know that you aren’t alone. React Native is wonderful, and you should try to embrace it with an open mind. Don’t pigeonhole yourself into what is comfortable like I did.
Step outside of your comfort zone and you may just find something even better than before.
Marc Shilling
is an interactive developer at Chalk + Chisel, a digital product agency, in Baltimore, MD.