logo-bs logo-dxn logo-odl

Our Journey Building a React Native App

Magento specialists, The App Store and The Play Store - three things rarely spoken about in the same sentence

Then an existing client of ours, one that’s been having month on month growth from an existing Mobile-friendly website we built for them, approached us with a new request: An App on both iOS and Android, capable of covering some of the offline features not currently possible on the Web.

Being a Magento Agency, we’re focussed primary on PHP + JavaScript development – so it seemed initially to be way out of our area of expertise. So should we let this client go elsewhere for this instead? That didn’t seem like a good idea. We had already worked with them for years and we know all about the complexity/limitations of their internal systems – there’s really no-one better suited.

Then we had an idea – what if we could leverage our existing talent in house to produce this App? That way the client wouldn’t need to work with 2 agencies and we’d get to learn how to produce software for 2 entirely new platforms!

So we started looking into the skill-sets sets required to pull this off:

  • Design – we would need visuals and UX decisions before anything can begin. Something we already have in house.
  • API development – App’s tend to be primarily API-drive and we’re a Magento agency – working with data & APIs is our bread and butter.
  • Finally, App Development. This would would involve either: 1. hiring Swift and Java developers to create the twice, once for each respective platform, or 2. utilise our existing Frontend developers if possible.

if something can be written in JavaScript, it will eventually be written in JavaScript.

It’s so funny, because it’s so true. Enter React Native, from Facebook.

React Native

React Native is a platform that allows Javascript developers to create Apps for both iOS and Android, all from the same Codebase.

It does not require developers to learn Swift, Objective C or Java as the business logic of the application will remain in Javascript, even when running on the device. But What makes React Native really shine is that the UI it creates will be native to each platform, so the performance will on par with Apps written in those other platform-specific languages.

There are other solutions out there than achieve similar results, but some of the reasons for choosing React Native were as follows:

  • It’s actively developed by Facebook – there’s a release every month!
  • It uses modern tooling – so we get to use the latest version of Javascript, as well as other cool feature like hot-reloading etc.
  • We get to write JavaScript – no need to learn 1 language per platform, we can leverage much of what we’ve learned on the Web.
  • 90% of the code is shared across the iOS and Android platform – there are just a handful of situations in which a platform-specific components are needed.
  • It’s not just a web view wrapper – React Native gives higher performance & tighter integration with the host platform than other tools.

So we had the answer now, yes – JavaScript developers can produce an application that will run run on both iOS and android (thanks to react native) but if only if our frontend developers were up to the task…

React Native is not for beginners.

Around the JH offices, you can often hear me repeating a phrase that I once heard from some other, much wiser developer:

don’t ever get married to a particular library or framework, or even programming style – instead become an expert at the underlying language

This is something I’ve always believed in and something I advocate for in our work here at JH. I don’t think it’s a good idea to become an Angular developer – or a React developer, you should instead strive to become an expert in JavaScript – doing so will allow you adopt new tools, libraries and frameworks as they come in and out of fashion without much work.

Because we follow this idea, the fact that iOS and Android were completely alien platforms to us wasn’t too much of a hurdle – we just needed to learn the ropes in React Native. So we dived in.

How we did it.

Along with React native, the following handful of tools were some of the most important we used to create the App.

Redux
Having the entire applications state within a single immutable store enabled us to impose a restriction on state updates that occur throughout the App – it’s a strict pattern of “UI raises an event -> reducers return a new state -> components re-render with that new state”. Also with Redux being so popular, there tends to be a middleware for each problem you encounter (such as persistence, logging etc) and the dev-tools experience makes debugging a breeze.

RxJS
Via redux-observable, we were able to move all of the side-effecting behaviours from components and instead place them at the edges of the application, into what are known as epics. These are just plain functions, but they exist outside of the lifecycle of any components and can observe all actions that pass through the store. This makes them perfect for the composition of async behaviours – and we use them heavily to power everything from Network requests, to Alert windows and Camera management – basically anything that does not fall under the React API, we wrap in Observables and compose at will. Handling all of the side-effects inside epics, rather than in components, allowed us to more gracefully handle errors and to retry or recover where possible – something that can get really tricky in raw React.

ESlint
On a project with hundreds of files, in a language as flexible as JavaScript, there needs to be some rules in place to ensure code styles are followed. We used a fairly common base configuration from Air B&B and then tweaked it slightly to include some React Native specific rules.

Flow-type
With so much of the app being powered by APIs, it made sense to introduce Static Types to our Javascript files. We can describe the ‘shape’ of data as it returns from network requests and then use that static information inside components – this helps to spot and fix bugs/typos whilst editing the code, rather than waiting for the error to surface via an exception in the App.

Flow allowed us to add these types in an incremental way, via the // @flow comment that can be added to the beginning of any Javascript file. We found this to be both a blessing and a curse. It’s sometimes great to skip type checking when you ‘just need to get something done’ – but the down side is that a calling a function that was imported from a file not containing that special comment, will receive zero type-checking, so that’s something to be aware of.

We’re big users of Flow’s rival Typescript here at JH, but were impressed with how far Flow has come along given it’s relative immaturity compared to Typescript.

Jest
There’s a huge amount of regular JavaScript that goes into a React Native application – especially when you’re handling side-effects away from components like we are with redux-observable. So it makes sense to have as this code under a test suit that exercises as much of it as possible. With it’s powerful mocking capabilities, Jest also makes it possible to test components and how they render using the test-render made available by react-native. This means in reality, our test suit is made up of both regular unit tests + what would probably be known as integration tests, but we don’t tend to worry about that distinction too much.

Lessons learnt.

Now that the App is live, and we’re well under way with new features and phases of work, we can look back and reflect on some the biggest lessons we learned during the process:

  • Don’t spend all your time becoming an expert in a single library, because we focus on becoming experts at JavaScript, we were able to accept a new challenge and ended up delivering to a platform we never thought possible.
  • Choose tools that make debugging easier. Redux, Redux dev-tools and other tools like these come into their own when your application goes wrong. There cannot be enough said about choosing tools that will help you in the bad times.
  • Use tools to automate the linting and auto-fixing of your code (where possible). Conversations about code style & syntax are a waste of everyones time, just set up some rules, and have everyone follow them. Even better, have your builds fail when they do not!
  • Write tests at as high a level as possible – if you can write just one test capable of exercising 5 function calls, and you can still assert on the inputs/outputs, then do it. Don’t aim for 100% coverage.
  • Get a grip on side effects, move your interactions with the outside world to the edges of your application.
  • Don’t put off adding error handling, it will always come back to bite you. Utilising libraries such as redux-observable can help greatly with this.

Summary

We were faced with a tough decision – 1) outsource work because it involved deploying to a platform we had no experience with, or 2) dive in head first and use our expertise in design and development to deliver what the client wanted.

We relished the challenge, drawing upon multiple areas of the team and ended up producing something we were all extremely proud of.

You can check out the App on iOS and Android.

Discovery Workshops: How to Best Kickstart a Project

Discovery Workshops: How to Best Kickstart a Project

Read More >

Getting Mobile-Ready for Your Peak Season

Getting Mobile-Ready for Your Peak Season

Read More >

Introducing Dwayne Codling, our new Front-end Developer

Introducing Dwayne Codling, our new Front-end Developer

Read More >

Start the conversation

Whether it’s a new site or an existing one, Jamie’s ready to respond to you on
jamie@wearejh.com or +44(0)115 933 8784