React Error Handling and sprinkles of MobX
Tags: react, webdev, javascript, mobx
Published: 2019-10-16 07:39:05

---
title: React Error Handling and sprinkles of MobX
published: true
description: Devising the error handling infrastructure of a React application with MobX
cover_image: https://thepracticaldev.s3.amazonaws.com/i/plfgnotaamoqsm0j0jni.jpg
tags: react,webdev,javascript,mobx 
---

This article is about sharing my thoughts for implementing a React application error handling infrastructure and augmenting it with the observability that [MobX](https://mobx.js.org/README.html) provides.

_If you need a refresher on React Error handling you can check the prequel at_
{% link https://dev.to/igneel64/yet-another-react-error-boundaries-explanation-15kf %}

Tackling error handling gracefully in modern frontend applications is not as easy as it sounds and can generate many questions that will indeed affect the whole experience of your product or service.

### How easy then ?
As an example for some of our own applications in my current company we would need to answer most of the answers below when an error occurs:
- Do I even need to do something ?
- Do I need to keep showing the loading indicator and retry ?
- Does this error signals a whole application failure ?
- Should I prompt the user to refresh or try again later ?
- Do I log this as an alert on our error reporting service ? (we use [Rollbar](https://rollbar.com))

Of course all of the above depend on the error that occurred and also on how complex the application is. 

__Just a tip__: Start small. If you don't have anything set up currently, just add a really simple screen for the user that faced an application failure. Apologise and give him a simple alternative, either that be calling support or wait until the issue is resolved. Don't leave him with a blank screen or even worse, a broken experience.

While trying to tackle this issue initially, we quickly got into the point that we would need to handle asynchronous operation failures. In our case network requests mostly for resource fetching.
![axios fetch](https://thepracticaldev.s3.amazonaws.com/i/8l7cyprqds3lzeoypeuv.png)
I am sure most of web developers out there have used code like this (ok it could be `fetch` or any other library but you get the idea). The event of a network request failure is something that most probably should be reflected in the UI, presenting the current state of the application. In the case of `handleError`, even if you `throw` the error, it goes unhandled through React and any set Error Boundary. Are they any good then ?

### Error Boundaries are good
As shown in the prequel of this post, Error Boundaries have the single responsibility of handling synchronous lifecycle/render exceptions, but in our view __they are so convenient__. You get to add a `Wrapper` that acts as an erroneous state replacement for any `Component`. Like that was not enough, you get to have as many as you want, each being able to handle specific case or re-throw for the next parent Error Boundary.


### How we approached the needs
So in my mind to reap the most benefits out of the native error handling mechanism we would need to have two things:
1. A __reactive__ way to handle asynchronous code faulty behaviours and exceptions
2. A centralized module that can fit the business logic categorizing error occurrences and __modify state__ as needed

What these initial thoughts triggered is reaching out to MobX and creating an `ErrorStore`, nothing fancy as of yet but enough for a start.
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/u94vfxvg7nuilescdeec.png)

By having this store at hand, we get a centralized place to add errors that we indeed want to handle more strategically. With just a simple `observer` [decorator/function](https://mobx.js.org/refguide/observer-component.html) we can get access to the `errors` member and allow any Component to get notified of updates.

Now this _centralized error handling structure_ can weird out many people but let me remind you that this will not be a replacement of any sort of error handling that you might already have in place, but an __augmentation__.

It may seem too explicit for some people and it might get confused with _manual handling_, but it is not. What I would like to see it as is more of an additional filtering layer that you either pass-through or handle.

### The good parts
As we have shown previously, the _asynchronous_ HTTP request Promise rejection, was left unhandled by an Error Boundary. To get a first shred of control in this I added this exception on the ErrorStore.
As simple as:
```javascript
axios.get("https://resource.example.com")
  .then( res => handleSuccess(res) )
  .catch( err => errorStore.addError(err) )
```

Now the requirement was that in the case of a failed response from this resource request, we would set an application level error and show a reduced availability screen to the user __as it currently worked with any technically synchronous React error__. Now this seemed really straightforward to do.
```jsx
const MyComponent = () => {
  const { errorStore: { errors } } = useStores();
  // useStores -> https://mobx-react.netlify.com/recipes-migration
  if(errors.length){
    throw new Error("It seems the request went wrong, let the Boundary handle it.");
  }
  
  return (
    <MyWellPlacedContent />
  )
}
```

As it is in technical terms, inside the React responsible code, when you throw, the error will get handled by the next wrapping Error Boundary.
#### __Success__! &#127882; &#127881; &#127882;


But this...
```javascript
  // ...
  const { errorStore: { errors } } = useStores();
  if(errors.length){
    throw new Error("It seems the request went wrong, let the Boundary handle it.");
  }
  // ...
```
seems to me as reusable HOC-ish logic. Something like a seatbelt (?!)...
```jsx
const withSeatbelt = (ComponentWithDangerousOperation) => inject("errorStore")(observer(({ ...otherProps }) => {
  const { errorStore: { errors } } = this.props;
  if(errors.length){
    throw new Error("Your logic");
  }else{
    return <ComponentWithDangerousOperation {...otherProps} />
  }
}));

```

The above HOC is naively listening to any error that happens and triggers the throw logic that would use the next in line Error Boundary. Instead of the `errors.length` conditional, you could start becoming creative. What I thought of adding:
- A HOC function parameter that defined `when` should I throw. E.g. `if(test(errors))`. This `test` function can search the array for a specific error you want for the Component to throw. 
- For higher reusability you can opt for adding the Error Boundary Component as a parameter, or even define a class of HOCs with specific Error Boundaries.


#### Logging, monitoring, tracking tip
What we usually do in the Error Boundaries of the React applications we manage is enriching the `componentDidCatch` lifecycle with the required cross-cutting logic that keeps us in control. Calling the required services to send the error to:
- Error tracking service (e.g. Rollbar)
- Logging warehouse
- Google Analytics

This can now be used alongside the `addErrors action` to also monitor these special kinds of errors. 

<hr/>

This structure shown above has allowed our team to think about the probable states of any Component that we are building and not the underlying error handling mechanisms it should cater for, either sync or async.
I hope that if you reached the end of this article you have managed to extract even one or more ideas for your next or ongoing React application error handling. I would also be eager to hear more opinions about this matter.

_P.S. If you haven't tried out MobX for state management, believe me you might be missing out on some state management pain alleviation._

_Image by <a href="https://pixabay.com/users/Quangpraha-7201644/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=3344508">Quang Nguyen vinh</a> from <a href="https://pixabay.com/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=3344508">Pixabay</a>_