React Native articles are back!

Hi friends! And welcome back to the continuation of the technical React Native articles! Unfortunately I ’ve been away from posting new articles for quite some time now as I was bootstrapping my own services company. But this is about to change today onwards!

Also, within the next weeks/months, we will be publishing quite some content on both technical and non technical subjects under our new Medium publication! I’m excited to be back on writing articles and I really hope you will enjoy them as well! As always if you have suggestions, shoot an email at social@codedlines.com or post at the comments section below. Thanks so much for your support over the past years and welcome back!

Image 1: Article preview image

Why best practises part 2?

Since my previous article, the landscape and tooling around React Native have changed, so I wanted to provide an updated post for React Native best practises in 2020. There are also quite a few more areas to cover, so this article is intended to work also as a continuation of the previous post.

Use Expo “managed workflow” only if you know exactly what you are doing

This is the same thing I mentioned 1.5 year ago and it hasn’t changed yet in my opinionated view. Having worked with both React Native and Expo apps, read below why I have come to this conclusion.

Expo has evolved quite a lot over the past months but it’s still a very limiting framework overall. The problem is that limitation applies in many sectors which we will mention and this is why I still have to say that if you want to learn React Native and become a solid mobile app developer, Expo is not the way to go. It’s a big no-no towards that direction.

Don’t take me wrong; Expo has evolved hugely and it really tries to simplify things but the thing is, it can only provide simplification for whatever it supports. Period. And in order to support something, custom development is needed from the Expo team in order to keep this framework running. It’s a framework on top of the React Native framework and in order to be evolved it takes time and dedication.

I have built production apps with both React Native and Expo, so let me elaborate on what do I mean with the term “limitations” and why I still don’t favor Expo.

Limitations

Native is limited by all means possible. And this is not a good thing, at least not yet. If you truly want to master mobile development, you need to learn how to use the basics of each platform like the gradle build system for Android and the Xcode for iOS. Expo tries to hide this complexity but not in a successful way yet. The process is not so easy yet and it just makes hard for everyone who is accustomed with the existing native process. Also if you think you don’t need the native side just because you are coming from a web development background (just like myself), you are wrong!

Specific examples:

Delays on when you get updates. The Expo team has to first develop and integrate RN updates for the Expo SDK to get the new updates and then release them. That takes up to many months :/

You have to deal with an extra framework, which means on top of RN bugs, you ‘ll have to face Expo bugs as well. And as every bug, fix might not be available soon.

Cannot access the native side, including installation of 3rd party packages with native modules and also protection from native crashes . This functionality is not yet available in Expo although is it available in React Native iOS apps as the community provided a Pull Request.

. This functionality is not yet available in Expo although is it available in React Native iOS apps as the community provided a Pull Request. Restrictions on how you automate your app build process. On simple terms, you have to necessarily create an Expo account and there are few CI products that support the automation of Expo build process so far.

You have to use extra tools like Expo client in order to install the app on your phone. And this in theory is OK for devs who don’t know the native side at all but you end up with performance issues when testing on the device through the Expo client. App is much slower than with the actual executable file.

The only cases I would favor Expo “managed workflow” are the following:

You have been building React Native apps for quite some time already, you know exactly what you are doing and you have concluded that for a specific new project and a set of reasons you have justified Expo is indeed a better choice. You want to check the world of React Native for the first and try some Proof of Concept (not a whole Minimum Viable Product though). There it makes sense to use Expo easiness of setup in order to start playing around faster.

Use React Navigation as your navigation library

Over the past 3+ years working with the RN framework, my fellow colleagues and I, have all come to the same conclusion:

No matter which navigation library we try, we keep coming back to React Navigation

Long story short about React Navigation:

It’ s very easy to install as it’s a JavaScript library without native modules (Expo also includes it by default — EDIT: as Brent Vatne mentioned it’s because Expo team built it!) It’s easy and rational to use, if you are a bit familiar with mobile navigation already It has started to achieve great performance and you no longer need to consider solutions that include native modules Has made quite a lot of progress over the past years — it is now in version 5.x — and is being maintained actively

If you want to give it a try I suggest starting with the official docs. If you are new to mobile development you might helpful my previous article, where I explain the different available types of mobile navigation and how they work, along with authentication workflow sample.

Handle & Log your errors properly

That’s a very important one. Nowadays, both React and external tooling have evolved a lot. That being said, we can now handle and also document our app errors so that we don’t have to suffer when a critical error occurs. Both points are very important here and will be analysed further below.

Include Error Boundaries to avoid UI crash

React library has provided a new tool to address UI crashes since React 16.3; it’s called Error Boundaries. As official documentation explains pretty well:

Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI. Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.

An Error Boundary in a component that can be created from any React class component; we just need to follow a specific methodology.

In every React Native application you create, you should always have at least one main Error Boundary component at the app’s highest level. That way we ensure that all errors generated in any aspect of the app, will be “caught” inside this generic Error Boundary exception handling mechanism and the app will not crash or fail due to unexpected JS exceptions as shown below:

<AppErrorBoundary>

<AppNavigator />

</AppErrorBoundary>

and this is how it looks:

Image 2: Error Boundary UI sample screen at highest app level

Now with this approach so far, we will be showing this generic error screen when things go wrong in terms of any JavaScript error within the app. It works but if the error is down the bottom of the JS functionality tree, it means that the whole application becomes non functional instead and users sees this screen instead of showing a more specific screen on where the error is located.

In order to address that matter, we can create more Error Boundary components that are specific to the screen and show a similar UI (minus the missing information/data which we were unable to fetch and that’s why something went wrong) In example:

Image 3: Specific Error Boundary UI screen

What we see above is a custom Error Boundary screen developed for the case that we cannot retrieve and show the image that should normally be visible where the yellow box lies. Instead of incapacitating the whole app with the use of image 2, we decided to create a custom Error Boundary screen and show it in plain black background. That way the user also understands that something is wrong with the image gallery not being able to load the preview of this specific image.

Of course it makes no sense to create Error Boundary screens for all of the application screens necessarily but it definitely does for screens that we identify as error proneous along the way. Error Boundary configuration will be shown in another post.

Protect your app from non UI JS crashes and hard native crashes

Your app needs to be protected against errors. An unhandled error means that your app will either not work properly in a partial or complete manner (JavaScript crash) or will become unstable and will close unexpectedly (native crash). The latter one is painful every single time. But we do get some tools to address it, like at least explain to the user what happened.

Handle JavaScript crashes all the way

The minimum way you should protect your app from JS crashes is with Error Boundaries mentioned above. But you can’t leave everything up to them. You need to provide try...catch statements wherever applicable. Standard situations include API calls, state manipulation, AsyncStorage invocation and pretty much everything that includes some promise invocation.

Handle native crashes

Native crashes are a true pain for all developers but it doesn’t have to be anymore. My suggestion here is, to make use of a package like react-native-exception-handler which allows to capture native errors and show an informing message to the user before the app closes unexpectedly.

Image 4: Demo gif file from the react-native-exception-handler repository showing how the app behaves with the use of it

Now this is not perfect. It’s still a bit ugly and if you want to customize the UI modal/message you need to edit the native side of this package. But at least it’s something, which provides user feedback in a clear way. It’s way better than having a better closing unexpectedly on startup and leading to annoyed users performing bad reviews in the app stores. That way at least, the app looks more professionally handled in case of error and implies that the developer team has a way of tracking these things and will fix it as soon as possible.

Use an external tool for error logging

In order to address properly all the error categories mentioned we need to log them. The easier way to do that is to integrate an external tool that is built for this reason. There are a few alternatives out there like Bugsnag, Sentry, Rollbar etc. Choose the one you prefer and get started with them.

They will allow you easy error logging and error identification. They can usually show you the line that your code crashes with outside of the box integration. But this applies only for the JS side and only for where the error occurred. If you want to know more info on like how the error appeared, in which screen the user was, what where the problematic data that were passed etc, you need to customize a bit further the functionality and make sure to provide the error to your tool inside of every try...catch

Make sure to use Hermes if applicable

React Native 0.60.4 has come with a new powerful tool to improve Android performance which is lacking in regards to iOS. It’s called Hermes and it’s JavaScript Run Engine. In Facebook’s words:

Hermes is an open-source JavaScript engine optimized for running React Native apps on Android. For many apps, enabling Hermes will result in improved start-up time, decreased memory usage, and smaller app size.

Unfortunately Expo doesn’t support it yet (SDK 36 was the latest available at the time of writing that post), so if you wanna try it, make sure you have the needed React Native version and check the docs on how to enable it as at this time Hermes is an opt-in feature and not enabled by default.

If you have used it already we’d be very interested to see the performance gains it has brought to your app, so please go ahead and share your experience at the comments!

What do you think?

What do you think about this article? Offer your perspective and ideas in the comments section below.