I’ve been writing mobile apps at Whitesmith for a while now and, for the majority of the journey, I kept a pretty skeptical attitude towards hybrid mobile development platforms. I cultivated this biased view of things for a while and I have to admit that the reasons were not that much related to performance or reliability but more with the threat that they were to my comfort zone.
When Facebook introduced React Native I noticed that the overall feeling regarding this new approach was somehow different from the rest. After the good experiences that some of my fellow and trusty Whitesmithians had with React Native I’ve decided that it was time to give it a shot. Android Studio and Xcode wouldn’t miss me that much and learn something new would be a good thing for sure.
Then I got lucky, a new project landed on our lap with two very good things for my goal: requirement for both Android and iOS and a very tight deadline. This is a brief sum about my experience over a month of learning and development and not wanting to spoil much: it was a lot of fun.
Language
Before starting this project I had close to zero experience with Javascript and that alone was enough to scare me a bit. Being constantly surrounded by web developers, hearing a few rants about the language is inevitable and some of them are pretty fun. However, I feel like I arrived at the Javascript station at a pretty good timing, the ES6 timing.
Concepts like classes, promises, constants and arrow functions quickly became familiar and it took not that much time to get things rolling. I’m willing to say that the learning curve is much nicer when compared to Objective-C, Java or even the mighty Swift!
Learning a new language was something that I’ve wanted to do for a while and doing just that with Javascript turned out to be surprisingly good.
Environment
Although Javascript is a considerably different thing compared to the traditional mobile development languages, it was in the environment that I felt the biggest changes in my workflow.
I first tried Atom, then the Nuclide IDE and finally settled with Sublime Text. Sublime Text with the ESLint integration works perfectly for me, it’s fast and lighter than the alternatives and it took me less time to assimilate the basic shortcuts. Using a text editor instead of the huge IDE’s was something that my 2013 MacBook Air enjoyed a lot. My setup features Sublime to edit code, the iOS Simulator to run it and Chrome for debugging. The live reload feature of React Native makes the experience even smoother.
But all of this doesn’t come without a price for someone that, like me, is a heavy user of the ctrl+space code completion features of both Xcode and Android Studio. This was, however, a problem easier to overcome that I initially thought and after a few days my brain just accepted the new way of doing things.
Two things that I don’t like that much on this setup: to run things on Android you have to use the emulator (I didn’t try Genymotion), and it’s just not as nice and fast as the iOS simulator. Every time I ran things on that my laptop fans went crazy and everything got a bit sluggish. This was an issue for me when I was trying to setup the specific bits of UI that Android needed. Another issue is the mandatory usage of Chrome as a debugging tool. It’s not much but since I’ve been using Firefox for the last couple of months I would prefer not having to use Chrome.
Despite all of this, and if I had to choose now, I would probably prefer the lighter workflow that React Native offers.
Write once, run anywhere
Here’s the holy promise of the hybrid mobile development. It’s obviously a chimera but with React Native you can get pretty close depending on the nature of the app that you’re building and the dependencies that you choose to include.
This app we built over a month never forced the choice of platform specific components or features and this allowed a fairly agnostic code base. This is something that you have to keep in mind when including third-party libraries because it might contain something that is only supported on one platform, breaking the compatibility.
Imagining that you write the simplest most agnostic code, when it’s time to run things on different platforms you’ll find that not everything looks exactly the same. Android has some ways of displaying text inputs that differs from iOS and this is just one of multiple examples. React Native does a lot of magic behind the scenes but ultimately you’ll have to take care of this kind of things.
On top of that, you have the specific and familiar behaviors of each platform. Android’s action bar is not the same as iOS’s navigation bar, iOS’s tabs are not Android’s view pages, you get the point. As mobile developers we need to make sure that the app looks and acts according to the platform that the user is using and going with React Native doesn’t excuse us as developers of this responsibility.
Building interfaces
Compared to my processes of building interfaces for mobile apps, the React Native gets way closer to Android than it does to iOS. When working with iOS, I tend to rely on Interface Builder to place elements and define relationships between them. Usually, I drag, drop, set constraints and then, just in case, I do a little bit of praying. While on Android, I write the layouts directly with XML because it’s easier for me to figure what things will look like while I’m writing the code.
React Native uses flexbox to build layouts and after a couple of days, I was working in a very similar way of my Android process. It was fairly easy to imagine the layout I wanted to define and write my components styling to get it done. You can use views, directions, alignments and other props to get everything where you want. While Interface Builder is great to quickly build a layout, I often prefer this more declarative way of Android layouts and React Native flexbox because I can deeply understand how things will appear and behave.
React
Man… I love the react way of doing things! It feels like everything on your app is a little bit smarter.
Instead of setting up components, waiting for, or coming up with data and then go back to the component and kindly ask for them to render what you need, with react you just tell your component to keep an eye on something that you consider important. When that changes, the component knows that it’s its business and deals with it. If, on top of this, you add Redux to manage the state of your app, things get even better.
Things I wish I knew
One month passed, it was great, I learned a lot and the app is (almost) done. However, there are still a few things that I wish I knew when I was starting the project.
Even if your app is pretty simple you should need a way of moving users back and forward and the best to do this is using an external library. I started with the React Native Router, it has a very simple API and it was a breeze to integrate and use. However, it was not very good supporting multiple platforms and when I had the need of integrating bottom navigation with a top bar I decided to move to React navigation. React navigation is the way to go, the API is not as simple but it’s much more robust and flexible, being much easier to make things look good everywhere.
Next, plan your Redux store ahead. I feel like I made the mistake of overusing it. Almost every property of my app is managed by Redux and this results in large reducers and many many actions to control all that. It’s very important to figure if some prop will be needed outside a certain component or not and, if not, keep that inside that component.
Another issue, styling. I kept writing styles inside my components, this is not a very advisable practice since it’s easy to end up with code duplication and styles that are not easily reusable. Keeping the styles separated and agnostic regarding components is a much better idea. I’ll write a second post just about this. Promise!
And finally, choose a nice folder structure. You’ll need to import lots of things across many files and the structure is important to keep everything consistent. I often write index.js on my folders to help to import stuff and another solution is defining a namespace on a different package.json file if you need.
Please give it a try
Give it a try, seriously.
I may have been biased by the novelty after years of heavyweight IDE’s and over complicated languages, sure. Even if this is true I think that there’s a huge value in this ‘new’ technology. React Native is not a solution to everything and it will probably not solve every demand that you might have with no effort, but it’s a fresh way of writing apps and a way that is gaining more and more momentum.
At this point it’s quite hard for me to imagine a future without (at least) thinking of what React Native could do to help me build my apps.
Don’t forget to share with us your experience and thoughts about React Native, find us on twitter!
The Non-Technical Founders survival guide
How to spot, avoid & recover from 7 start-up scuppering traps.
The Non-Technical Founders survival guide: How to spot, avoid & recover from 7 start-up scuppering traps.