Handle your Errors with Error Boundaries

Error Boundaries — What are they?

React 16’s Error boundaries help you make sure that an error in part of your UI won’t break the whole app. Error boundaries basically does 3 things:

It catches JavaScript errors in the child component tree

It logs these errors

It displays the fallback UI

In this section, I will show you how to create an Error Boundary for your app.

Example App

I have created a new React app using create-react-app and I’ve written the following code in my App.js file.

What is happening in this App?

This is a simple application that renders a Profile . The Profile component expects a user object with the property name passed inside it. I also have a button that updates the user. Run yarn start and see that it works perfectly.

But, the app will break down when you click on the button.

This happens because the onClick function of the button is passing a null value for the user . This will throw and Uncaught TypeError since the app cannot read the property name of null .

Solution

To handle such errors, React 16 has introduced a new lifecycle method called componentDidCatch . This method will allow us to catch any JavaScript errors from anywhere inside a component’s child component tree.

In order to inform me that something is not working as it should, I will update my state inside this lifecycle method, and indicate that an error has occurred.

Make sure to add hasError: false in your state object.

Then in the render function, add a conditional statement that checks the value of hasError and renders the fallback UI.

It’s important to include this behavior because errors which are not caught will result in an unmount of the whole React component tree.

This wasn’t the case in React 15 and lower, as the UI stayed untouched there. This behavior has changed because the React team felt that it would be worse to leave the corrupted UI in place rather than completely removing it.

Coming back to componentDidCatch , it receives two arguments that will allow us to track and investigate our errors. These arguments are:

error — This is the error instance itself

— This is the error instance itself info — This argument contains the component stack.

This is especially useful when you’e running your app in production mode, as it will use an error reporting service to check exactly where the component broke down.

With this, the App component can be described as an error boundary. The next step would be to extract the error boundary’s functionality into a separate component, so that we can use it everywhere in our app without having to write the code again.

Error Boundary

Create a new component called ErrorBoundary as shown here:

This new component contains the hasError state and the componentDidCatch lifecycle method. The app’s render method has the fallback UI for when an error occurs.

Remove the hasError: false and componentDidCatch method from the App component. Inside the render method, wrap the Profile inside the ErrorBoundary component like this:

Error boundaries work with deeply nested component structures. So it would best to put it in a few strategic places, rather than at every level.

The error boundary is now capable of catching errors and rendering the fallback UI!