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:
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
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.
This allows us to utilize this components to capture errors and display a fallback UI in case of an error like so:
And that is literally it. If the
counter component throws an error the ErrorBoundary will handle it.
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
- We can be as granular as we want with it — wrap individual components or entire application pieces
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.
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.