Lessons in adding Offline Mode to a React Native app for iOS and Android

Sandy Lewis
AgriDigital Engineering
5 min readApr 9, 2021
Photo by Luca Onnboni on Unsplash

You’ve done it! 🎉 You wrote your first mobile app. It took a lot of time and late nights but your app is in the app stores and people are loving it. One of the features that your users start clamouring for is the ability to create data when they don’t have access to the internet. Time to start planning!

You know this is going to be a tricky one. You’ll have data now being stored on device and keeping that up to date is going to be a challenge. Product and engineering teams get together and work out that:

  • There is one core feature that needs to work offline
  • All other features will show an offline message
  • The connection state changes are automatically detected
  • Syncing of data is automatic
  • A user has to be online to login and fetch the data needed for offline use

Whilst this is a fairly focused introduction to offline, there is still plenty of planning that needs to go into the implementation. The engineering team drills into the detail and decide:

  • SQL lite is the database of choice
  • The data that needs syncing is determined and it’s importance
  • A sync manager will be implemented that syncs the data on various intervals/triggers based on importance
  • A connection state manager will be implemented to automatically detect internet connectivity and update redux
  • The navigation manager will intercept routing to any components with offline unsupported and display an offline message

This is the most that you have planned for a new feature. You work solidly over several sprints to implement the feature and you have testers working through the process with you to iron out any bugs that crop up. You demonstrate to the business and you’ve been given approval to release to the app stores. The app is approved by both app stores and finally the feature is out there in the hands of your users.

And then the support calls start coming in… 🤦‍♂️

That was our story

Despite having the most amount of planning we’ve ever had for a new feature and extensive testing, our first release of offline mode was a failure. The reason for this can be summed up as:

Lesson 1
The real world is not black and white, but many, many shades of grey

What we had failed to consider in our testing is the shades of grey. We tested Wi-Fi and 4G in a major city with an uninterrupted connection as well as the phone in airplane mode. Our users operate in areas with poor cellular coverage and this is where most of the issues could be found. We relied on a component to tell us whether there was an internet connection or not but what we found was:

  • Users would be in areas with 1 signal bar of 3G and whilst technically connected to the internet, there would be insufficient bandwidth to process the data needed for an online transaction
  • Users could have no signal bars shown on their phone but the device had not switched to “no signal”.
  • The connection state is not updated immediately so a user could be mid-transaction, there’s no internet connection but the connection state has not updated yet.

The reality is that there is no good way to automatically manage the connection state for users that are in really poor coverage areas. Whilst we have added bandaids to fix the immediate issues by way of a manual offline toggle, this is not a long term solution.

To the future

We’re moving forward by making our app offline first. For any data created on device, this will be saved first to the local database. We’ll then use syncing processes to get that data to the server once the user has connectivity.

Lesson 2
If I were to start a new app today, it would be offline first from day one.

The process to retroactively add offline first is certainly not easy, but we’ve broken our process down into the following:

  • Isolate core processes to prevent unintended side effects. The connection state manager is an example of this.
  • Keep data on device for longer. The less that the app has to sync the better the experience for the user.
  • Eagerly sync critical data and delay larger updates for particular connection states (e.g. Wi-Fi)
  • Give the user more control over what connection types are available for syncing. e.g. Only sync if 4G or Wi-Fi
  • Modify all data creation/modification events on device to save to the local database first with a flag for the sync manager to detect and sync.
  • Enable background processing to handle some syncing tasks.
  • Testing, testing, testing. Automate as much testing as possible then focus on testing in those grey areas where your user resides.
  • Get a beta app into the hands of your key users to get early feedback.

Lesson 3
Spend time using your app in the environment where your core users operate

Whilst our initial release of offline mode in our app was a failure, we reacted quickly to mitigate the biggest issues. We released weekly updates with bug fixes and small improvements that made a big difference to the experience for users — namely manual offline mode. Users know the environment they work in and so can modify the connected state based on the quality of their connection. Having a failure has been a big learning experience and I’d argue that we’ll ultimately have a better quality product in the long run as we put more focus on planning, code quality and broader testing.

Life Lesson
Don’t hide from your failures. Learn from them, and let them be a lens through which you view the future.

Here at AgriDigital — we are focused on powering the worlds grain supply chains. Our two main products are:

  • AgriDigital — for grain buyers/site operators — Contracts, deliveries, inventory, orders, invoices and payments are easily managed from one simple platform a whole team can use — https://www.agridigital.io/products/agridigital
  • Waypath — for farmers — Inventory management tool that enables farmers to track their grain from paddock to payment, know their position and make informed marketing decisions — https://www.agridigital.io/products/waypath

--

--

Sandy Lewis
AgriDigital Engineering

Head of Mobile at AgriDigital. Avid baker and proud father of two [He/Him]