Could you introduce your app in a few sentences?
The app was designed as a directory and payment app for users of the Bristol Pound local currency. The base functionality facilitates browsing the local businesses that accept Bristol Pounds via an interactive map. For users who have an account with the Bristol Pound, the app also serves as a means of making payments to businesses, viewing past transaction data, or even withdrawing physical Bristol Pounds from designated cash points.
The app supports iOS 10 and above, as well as Android >= 4.4 (which covered over 85% of android devices at the time of development).
What made you decide to use/switch to React Native?
Our partnership with the Bristol Pound on developing this app was mutually beneficial; they would get a functional app for their users, while our developers would attain valuable mobile development experience. Here at Scott Logic, we pride ourselves in experimenting with all kinds of new and emerging web technologies, not just so that we’re well placed for future business opportunities, but also out of passion and curiosity. Colin (our CTO) had some experience with React Native from a very early point in its infancy, being part of the beta program. After this experimenting, he foresaw the usefulness of being able to develop an app with a cross-platform framework while maintaining native feel and performance in terms of UI.
This emerging technology then proved to be an ideal candidate for developing the Bristol Pound app, as well as providing a fantastic opportunity for some of our developers to familiarise themselves with a framework that would grow in popularity over the years. As the technology rises in prominence, we should be prepared for existing and potential clients to approach us regarding React Native platforms. Given that we already had a set of readily available developers with React experience, it seemed like the perfect time to make the switch.
How did you transition to React Native?
Given the nature of this project, it was typical for developers to spend a period of time working exclusively on the app before they would be moved on to another client project. As such, it wasn’t uncommon that the entire development team working on the Bristol Pound could change in a given month. It was one of these intervals between developer teams that was identified as an ideal opportunity to make the switch to React Native. With a completely new set of developers on the project, the transition was very much a case of starting fresh with a complete rewrite.
React Native was still considered in its infancy at the transition point, with a lot of the best practices and other documented knowledge yet to be as widespread as they are today. As such, the stages of development were more explorative in nature, with some iteration involved as more common techniques began to emerge from the React Native community. Despite this, the developers placed on the project were fluent in JavaScript and well versed with React, ensuring a high rate of progress early on. Once the RN packager and the emulators were set up, the differences in development processes between React and React Native were found to be relatively minor. Thus overall, the transition was pretty smooth!
Have your tried other cross platform technologies before using React Native?
Our initial implementation used Ionic, an HTML5 framework based on Angular, distributed via Apache Cordova.
Ionic gives a good developer experience, which is pretty much the same as web application development, being predominantly browser-based. However, we found that the technical constraints of Ionic were shaping our designs. The application UI was primarily list and drill-down, because this is what is easiest to achieve. We really wanted this user experience of this application to be first-class, without being constrained by the UI framework.
What has your experience been working with React Native in terms of app performance, have you noticed any impacts?
It’s no comparison between using a ‘headless browser’ style app and using native components. The general look and feel is more authentic and in line with the quality that modern smartphone users have come to expect. The responsiveness of UI elements such as ScrollView/ListView is consistently smooth due to them running on the native thread. Of course, the optimal performance will only be achieved through developing an app natively for each device type. However, as the nature of our app meant that it was essentially an interface that communicated with a backend, with no heavy processing, it’s unlikely that we’d have experienced a noticeable difference if we developed the app natively (other than startup time). As such, our decision to use React Native was vindicated, and the technology proved well suited to us in terms of app performance.
Having developers who are knowledgeable of React best practices also undoubtedly made a difference to the performance of our app. This was primarily down to being sensible with the component lifecycle, using shouldComponentUpdate
and assigning ‘keys’ to components, ensuring no unnecessary rendering was done etc. There was one troublesome case where we were performing an animation via using the Animation library to change the position within a style object of a component, while at the same time processing some data and sorting a list. We discovered that both of these operations were taking place on the JS thread, and on older devices the animation would sometimes appear jittery. We resolved this issue by changing the specific way we were animating the component and using useNativeDriver
so that the animation would instead run on the native thread.
How has adopting React Native affected developer productivity?
The speed of the development process saw a big increase since the move to React Native. Furthermore, another sharp increase was seen with the adoption of Expo. Having developers in-house who are familiar with React allowed new developers to come on to the project rather seamlessly. The rate at which features could be added to the app and tested both in terms of unit tests and user acceptance testing was much greater than could be previously achieved. Specifically, it was a delight to be able to add a feature, publish it to an Expo host and share it with another off-site team member so that they can test the app on their own device.
Which tools, libraries and frameworks are part of your development process with React Native?
When we began building the app in React Native, Expo was not the de facto method of development as it is today. Before this, the bundling took a lot longer, and running the app on both real devices and emulators during development was much more tedious and less reliable. We therefore welcomed Expo with open arms, having the Android and iOS specific build code abstracted away. The ability to just scan a QR code, or upload a build and share the url to other developers made things much easier. We used the Expo XDE for starting the builds and logging to the console, which both performed much better than the original React Native equivalents.
By the end of the project, we all tended to use Visual Studio Code for developing, owing largely to the React Native extensions offered: debugging and triggering Redux actions directly.
A key tool in inspecting the state of the React ‘tree hierarchy’ was the react-devtools standalone app , which is commonly used as a chrome dev tools extension for standard web based React projects. This proved invaluable as it enabled us to inspect elements directly from the emulator (or even live on a device running Expo) and observe the props and state of the tree/components in real time in this standalone electron app.
Of course, redux was fundamental to our app, and we used redux-persist to store the necessary app data to the device. This allowed us to keep all of the businesses data on the device, just fetching it periodically.
Our process of actually making releases of the app was a little unorthodox. We had one central github repo in which we develop the app with all the Expo environment setup in place. At the same time, we had another local git repo that we created via ejecting from the Expo environment. This second repo, while having the same remote as the main repo, was used exclusively for building releases, with no development work being done and no pushes to the remote. We would therefore go through a typical cycle like:
Develop with Expo in main repo > push to github remote > pull new changes into secondary ‘build’ repo > make any necessary changes regarding android/ios config files > build a release.
There were a couple of reasons for this:
Firstly, we maintained full control of the build code in the Android/iOS folders, such as versioning, API keys, secrets etc. On top of this, there were a few areas in which we used Expo specific code for location permissions etc. When fully ejected from Expo, the app cannot use any Expo code, so this was replaced with standard RN geolocation code. In general, this code very rarely changed, and the tweaking only needed to be made once.
What resources have you used to learn React Native? Books, tutorials, courses etc. Anything you can recommend?
As far as resources go, the support wasn’t as widespread as it is today. We always tried to upgrade to the newer versions of React Native while simultaneously updating the Expo version. We found the Expo release notes to be very handy in terms of realising what is now possible in React Native, and what we may want to incorporate. Other than that, the official docs themselves were often sufficient when solving problems. This small article also proved valuable for squeezing more performance out of the app, particularly at the finals stages of development.
What are some things that you don’t like about React Native or that need to be improved?
KeyboardAvoidingView
proved to be exceedingly tedious during the development of the app. It seemed to work as expected for iOS and then not for Android, meaning we had to apply certain ‘hacks’ to get it to behave the way we wanted. Each time we updated the version of React Native, this component never seemed to have been fixed. For such a common scenario (shifting views to avoid the keyboard), we would have thought this would have been rock solid. It’s been a while since I looked into this so hopefully it’s fixed now! Other than this, there were only a few other niggly cases where something in iOS didn’t quite match up to Android, or some property or method was only available on one platform. However, this was to be expected in the early days of the framework, and I imagine over time these will become ironed out.
Anything else you would like to mention?
To find out more about Scott Logic, and the work we do, why not take a look at our tech blog: blog.scottlogic.com