Diving into mobile with React Native

Shrey Gupta
Affinity
Published in
7 min readNov 29, 2017

--

A few months ago, Affinity ventured into new territory for front end engineering: mobile. Since many of our users are busy executives who spend much of their time on the go, we knew a mobile app had to be a core part of our product lineup. This blog post outlines how two of us on the engineering team took a chance on React Native to build out the mobile counterpart for our web app. The meat of this post outlines how we solved a few particular problems with React Native (navigation, data consistency, and animations). Feel free to jump straight to the Learnings section below to read about these challenges.

Background

Before starting anything at all, we had a few questions to ask ourselves…

Do we need to build an app for both iOS and Android?
Yes — as with most companies, our customers used a mix of iPhone and Android devices, so we needed to support both.

Do any of our engineers know Swift or Java?
Yes and no — most of our engineers had used Java but had never used it to program an Android application. None of us had used Swift before.

Do any of our engineers have extensive prior mobile experience?
No — some of us had worked on simple mobile apps, but no one had built a sophisticated enterprise product on mobile before.

Should we invest the time to learn Swift and Java?
Ideally not — we wanted to hit the ground running and make it easy for future engineers to apply their web skillset to mobile as directly as possible.

Are there frameworks that allow building a single app for both platforms?
Yes — there were (and are) many such frameworks out there, like Xamarin, Ionic, jQuery Mobile, Ratchet, React Native, and many more.

Decision

Our gut told us that we should build this app with a JavaScript framework so that 1) it worked on both platforms and 2) wouldn’t require a huge learning curve for our engineers, who already knew JavaScript very well. Our web app is build on React, so it made sense to check out React Native. We’d really enjoyed programming with the React paradigm on the web, so we were excited to use it on mobile and transfer all our React skills and best practices to this new platform. We knew that as a relatively new technology, React Native might have its flaws, but we were confident that with Facebook behind it, we were moving into a technology ecosystem that would strengthen and grow over time.

Strategy

Given intense demand from customers, we wanted to build this app fast. Another engineer and I allocated 7 weeks to build all of it out. Luckily, we knew that we could reuse most of our existing API endpoints. A few endpoints would have to be different, of course, because mobile required a few data representations that were different from the website. None of our React components from our website would be usable on mobile; HTML tags such as div mean nothing in React Native, which uses native UI components rather than HTML elements. We had to familiarize ourselves with using View and Text instead and write all components from scratch.

With those constraints in mind, we broke down the application into the different screens that the user could access, as mocked out by the design team. We divided the project based on how much work we thought each screen would take, created a 6-week plan with weekly milestones, and gave ourselves 1 additional week as a buffer to account for unexpected obstacles.

Learnings

We’re very happy that we went with React Native. It’s a powerful framework and surprisingly easy to learn.

On our journey towards a successful and on-time launch, we faced a few tough engineering problems. I’d like to highlight a few of those and share the tips we came up with.

A guide to navigation with React Navigation

A classic example of tab navigation

Navigation is a fundamental necessity for any application with more than one screen. There are 3 basic types of navigation: tab, stack, and drawer. Tab navigation is generally seen on the bottom of the screen, where each tab represents a different entry point into the app. Along with the navigation on the bottom of the app, there has to be some sort of navigation within each tab so that clicking on a certain element can take you to a new screen. This is known as stack navigation. (Drawer navigation is a third navigation pattern that we didn’t end up using.)

Stack navigation

To maintain all this navigation state, we decided to use a library called React Navigation which included the tab navigator UI container and the state management for both tab and stack navigation.

One of the advantages of this library is that it’s very customizable. For example, it allows you to manually manage navigation state. We took advantage of this because we wanted our push notifications to navigate the user to certain pages in the app (where some screens may be nested in the stack); React Navigation has a detailed guide for this.

With any app, screen tracking is very important and goes hand-in-hand with navigation. It’s important for things like controlling the color of the status bar, where the color might change depending on which screen is displayed. In order to do this manually, this guide from React Navigation advised creating a screen recording Redux mix-in.

One problem we had to solve for was resetting the stack navigation for a particular tab. Stack navigation may contain 10 screens, so if you want to go back to the first screen, you have to hit the back button 10 times. A common pattern to solve for this issue is to simply double tap that tab to reset the stack. React Navigation didn’t have this functionality out of the box, but luckily someone had made a PR for this feature and it had already been approved by the React Native team (though not yet merged in). We forked the repo with the proposed change and used it to build this feature out. This feature has now been added to the standard React Navigation distribution (details can be found here).

Overall, we found React Navigation to be a solid and useful library. We did face a few issues and had to write some custom code to perform screen tracking and manage navigation state, but we’re really happy with the results.

Resolving data inconsistency on mobile

Data consistency is a common problem on web apps. On mobile apps, it’s even more pronounced. When you’re using a browser, opening a new tab or window fetches up-to-date data from a server automatically. On mobile, in contrast, when you move to a new screen, update data, and go back, the data on the previous screen doesn’t update — the screens are stacked, and popping a screen from the top of the stack doesn’t re-render the screen beneath it. To avoid showing users inconsistent state, we needed data to be updated instantly, so we decided to use Redux to manage our global state. In retrospect, we wish we had integrated a Redux store into our code earlier to avoid the monotonous task of converting existing code to Redux.

Styling elements with React Native

React Native uses JavaScript stylesheets and inline styles for styling its components and everything is display: flex. If you know flexbox, then you’re probably thinking: that’s awesome! When we first started, we had never used flexbox and didn’t really know what to think. A lot of our styles for web relied on things like display: table and float: left. These styles work, but they often became overly nested and complex. Flexbox made our lives much easier — it just makes sense when you read and write it. We shared our learnings with the rest of the engineering team, and now we style elements using flexbox on web as well as mobile.

A person profile in our mobile app, styled with flexbox

Animations

Animations bring life to mobile content and can make a user’s experience much more enjoyable. React Native provides a great animation library out of the box. If you plan on using animations, take some time to read and try out a few of the different examples.

In our app, we wanted to give users the ability to take action on an item by swiping left/right on it (similar to taking an action on an email in many mail apps). We found many libraries online, but they didn’t cater to our specific needs. For example, a lot of them had great animations but didn’t let us customize the styling of the action buttons. We also wanted to add a small jiggle animation if the user clicked on a row to teach them that the row could be swiped. We ended up writing a component ourselves that mimicked the core behavior of other open source components but with these added features.

Should you use a third party library or build it yourself?

As mentioned earlier, React Native is still a fairly young library. Although a ton of great companies are using it, there’s still relatively few mature open source components available. Quite a few times, we found ourselves evaluating open source components that looked nice but didn’t quite cover all of our use cases. We had to write our own custom components, which took time but also provided us with invaluable knowledge for when we work on the next version of our mobile app. We’ve also realized that some of the components we’ve built out might be really useful for others, so we’re considering making them open-source them in the future — if there are particular components mentioned here that would be useful to you, please let us know!

--

--