Handling Errors in Vue with Error Boundaries

Dealing with errors is an integral part of building an application. Have you ever had a v-for not render the elements in your list due to an unforeseen error on only a single one of those elements? What about during text interpolation? Or any number of errors. The result is usually the same, the UI breaks. For example:

Entire `v-for` broken due to `null` value on a single element

In Vue 2.5 the errorCaptured hook was introduced and opened up some cool opportunities for handling errors in Vue applications. React 16 brought an idea of an ErrorBoundary component which could capture errors on a component and handle it accordingly so the entire app would not break. Let’s see how we can create something similar utilizing the errorCaptured hook.

Anatomy of an ErrorBoundary Component

For a component to be an ErrorBoundary component it must have the errorCaptured hook. Furthermore, it should be able to conditionally render between a fallback UI or its children. And that is pretty much it.

Simple ErrorBoundary Component

This allows us to utilize this components to capture errors and display a fallback UI in case of an error like so:

<error-boundary>
<counter />
</error-boundary>

And that is literally it. If the counter component throws an error the ErrorBoundary will handle it.

Benefits

There are a few benefits of it doing this way.

  • Helps to keep components free from error handling logic
  • Allows us to use declarative component composition instead of relying on imperative try/catch
  • We can be as granular as we want with it — wrap individual components or entire application pieces

In Action

Let’s create a simple ContactList component which renders a Contact component which will just present us with our contact’s name and phone number.

Building the ContactList Component

Our ContactList will v-for over a list of contacts and pass each contact as a prop to our app’s Contact component.

Building the Contact Component

Our Contact component will accept a contact as a prop and render the name and the phone number…without the hyphens though!

If we were to run this we would come across the same exact issue demonstrated in the Codepen in the beginning of the article. Since our good friend Leonardo da Vinci has a phone number of null when it reaches our withoutHyphens filter we cannot access the .replace method so our app throws an error. Thus, the list does not render at all.

Error Boundary to the Rescue!

It would be a better user experience if the application displayed something to let us know what’s up. This is where the ErrorBoundary shines.

Let’s refactor our ContactList component to utilize one for each of its Contact children.

And that’ll fix it. The ErrorBoundary will capture the error from the Contact component and instead render <p>Something went wrong</p> .

Here is a working example based on the above utilizing my personal ErrorBoundary component.

Caveats

There are some caveats when utilizing the errorCaptured hook. Currently, errors are only captured in:

  • render functions
  • watcher callbacks
  • lifecycle hooks
  • component event handlers

So if you have an @click="someMethod" and you throw an error in that method, the errorCaptured will not be invoked. But it looks like they are looking to change that based on this issue.

Another scenario to look out for is if the child you are wrapping is a functional component. Linus and Evan explain why in this issue.

Additional Reading

  • Vue API Documentation for errorCaptured — provides more details about the parameters errorCaptured receives and how errors propagate
  • Error Handling in React 16 — where I drew inspiration to build this component and see if Vue had something similar