How and why? That’s the question that came to my mind years ago when I first faced error handling in my app. Back then, it ended with “I’ll do it later” and doing absolutely nothing.
However, sooner or later comes a moment when, an error that you left behind punches you in the fact and says: ‘You will never leave me again’. That’s when you realize that you can no longer sweep it under the rung. You have to handle it somehow. But how? What tools to use? In this article I will try to answer this question and demonstrate how how to use react-native-notificated to inform users about errors.
You can find the repository with the code used in the article here.
Before we move on and talk about ways of handling individual errors, let’s think what kind of error categories we have. In my opinion, the most obvious and actually, the best one, is division according to the error ‘location’. Below you’ll find three of the most common locations:
Let’s see how the app will behave in debug mode without any errors handled:
Clearly, the app is throwing errors or showing a loader without informing the user about what’s going on. It would look even worse in release mode. The app would crash or freeze and that’s the opposite from what we want, right? So, let’s not waste our time any more and take care of each scenario individually.
The first group of errors appears in the component render method. Let’s handle them with the react-error-boundary package, where the documentation says:
This component provides a simple and reusable wrapper that you can use to wrap around your components. Any rendering errors in your components hierarchy can then be gracefully handled.
Let’s try to implement that. First, we need to create a simple FallbackComponent, which will be displayed when there’s an error:
The next step is to wrap the component that could have errors with ErrorBoundary and to pass FallbackComponent and onError handler to it:
If we run our project again, we will see that the app isn’t showing a render error anymore. Instead, we’ll see FallbackComponent that we created before.
This group of errors can’t be handled with error boundaries, which is why we need a different approach. The easiest method (and overall the best) is to handle it with a simple try catch block, built in JS.
Here’s what the implementation will look like:
Nice, we consoled event error so it doesn’t appear on the screen anymore.
The last type of error occurs when the screen can’t be rendered due to server bugs. In response, we get the error with a proper status code from the ‘fetch’ feature. Based on this code, we can handle the error with a reusable axios interceptor.
Let’s jump straight to the code. First, let’s create a AxiosInterceptorProvider component. Inside it, we need to set up our interceptor:
Now, let’s wrap our app with AxiosInterceptorProvider:
That’s all. Each time we call the axios fetch method, our interceptor will trigger and handle the possible errors.
Given that console.logs are not meant to be seen by users and we usually get rid of them during release builds, we have to use some visual way to show feedback to users. For me, the best way is to show some kind of an in-app notification, like a box or a snack bar. This is exactly what we can do with react-native-notificated, which is our new library capable of doing such things! It’s fast and highly customizable, so I highly recommend you check it out!
Setting up react-native-notificated is fairly straightforward, as you can see below. Since we want to customize it too, we will create our own notification component which we will use to overwrite the default component. Feel free to look into the documentation for more details:
Let’s start with creating a basic notification component and styling it. This is how our future custom notification will look like:
As mentioned before, react-native-notificated delivers nice notifications by default, but for this example we’ll customize them with CustomNotification component that we declared before. Let’s also assume that we want the notification to appear at the top for 5 seconds. We can do this with a simple config object like below:
Nice. But how about changing the animation a bit? Let’s say we want our notification to fade in and zoom in from the top of screen. To do that, we need to import one of the built-in animations and add it to the config. You can also declare your own animation from scratch, that’s how highly customizable our library is! Check the documentation for more details here:
Next step is to wrap our app with NotifyProvider:
Finally, let’s use our custom notification to replace console.log() in the application:
That’s all. Now, thanks to react-native-notificated the user will know when the error occurs and what’s going on. He won’t be confused anymore. Let’s look at the behavior of our app:
That was simple, right? It only took us a few minutes and believe me when I say that it saved us a lot of headaches in the future. Error handling doesn’t have to be unpleasant at all. It all depends on the approach we use. In my opinion, the number of available tools is so large that everyone will find something suitable.
The tools that I presented in this article seem to be the most universal and sufficient method to handle erros in simple projects. In addition, react-native-notificated can be used not only to handle errors, but also to inform the user about everything that’s going on in your app. The same goes for axios, which you will usually use in your app anyway.
Of course, we can do much more than that. For example, in addition to handling errors, we can also monitor them using the Sentry library. Check out the Sentry documentation for more info.
I hope that after reading this article, you will have a different perspective on errors in your app, and you’ll never let them surprise you again!