- Part 1 - Getting Started with Monitoring React Applications
- Part 2 - Automatic Logging with Error Boundaries (this post)
- Part 3 - Using AppInsights as a React Hook
Error Boundaries is a new feature introduced in React 16 to better handle unexpected errors that happen when a component tree is attempting to render.
The goal of Error Boundaries is to ensure that when an error does occur during render React has a way to catch that error in a component and handle it gracefully, rather than the component tree being broken and resulting in a white screen for the user. This all works by using a new lifecycle method on a
componentDidCatch method receives two pieces of information, the
error that was thrown and
info which is the component stack trace. This sounds like information that would be really great for us to track in an error monitoring platform, like, say AppInsights!
Designing Our Component
Let's create a generic “App Insights Aware Error Boundary” component, which will allow us to place a boundary somewhere in our component tree but also be generic enough to use in multiple places. After all, we don't want a single error boundary, that'd be akin to wrapping the whole application with a
catch block and make it harder to handle errors-at-the-source.
Our component will take two
onError. The first is the AppInsights instance you would initialise within an application, as we did in the last post, the other is the component to render or a function to return a component.
Using Our Error Boundary
I've created a demo application using the Gastby eCommerce starter kit (like last time) that shows how you can use an Error Boundary (source code is on my GitHub).
Since it turns out it's hard to create a reproducible error in a well-written application I've created a fake error scenario, basically whenever you try to add more than 1 item to the cart it'll throw an error during
render (error in codebase).
Before seeing the error boundary in action, what would it look like if we didn't have one?
Without the error boundary, we end up with a blank screen because the whole component tree has become corrupt.
Now we wrap our “buggy” component with an error boundary and if we click the ‘Add to Cart’ button we successfully added to cart, but if when you try to increase the number in the text box it throws an error and the error boundary is displayed.
How does that look in code? Well, we wrap the component we want with the error boundary (source):
Because I've got a really basic component to put in when there's an error, I'm just created an inline function component, but you might want to provide a proper component reference instead.
Inspecting Errors in AppInsights
By logging into the Azure Portal and navigating to your AppInsights resource you'll be able to filter the data to the exceptions you've captured:
The information might be a little tricky to read if you're using a minified bundle, but to help with that you can upload your Source Map and have it help give you more detailed information in the logs!
AppInsights will automatically capture unhandled errors that reach the
onError event in the browser, but when using React you want to do something that'll allow you to handle the component tree failing to render, which is where Error Boundaries come into play. We can then combine this with AppInsights to have our Error Boundary log those handled errors, you could even provide additional information to the properties of the tracked events if desired.