How to Use Error Boundary in React (Using a Simple Counter as Example)
Tags: beginners, webdev, react
Published: 2023-01-09 21:16:06

Hello Techies!

Today, I will show you how I learned to use Error Boundaries in React using a simple Counter as my example. However, before I begin I would like to share a little backstory…

Theoretically, I understood the importance of error boundaries but for some reason, seeing it in action or getting it to work was beyond me. So I made it my mission to understand the practical ways you can use Error Boundaries in React and I’m happy to say that I succeeded. 

For newbie techies like me who have struggled to implement an Error Boundary, let me show you how I overcame it.

## Prerequisites
Of course, to follow this tutorial, you need to have: 

- Basic knowledge of Javascript
- Some familiarity with React

## Why Do You Need Error Boundaries?

Errors are inevitable while developing your apps. Errors can be thrown from trying to access a nested property on an object that is nonexistent in your code. Sometimes, they’re not even in your control, e.g., server-related errors).

As a result, many methods have been created to cover our tracks and prevent these tricky errors from ruining both the developer and user experience. One method is the use of Error Boundaries to catch unexpected errors in the render stage.

Before the introduction of Error Boundaries in React v16, an unforeseen error would have caused the component to completely unmount itself, and the only thing the user sees would be a blank HTML page. For users, this is not ideal as they’re left confused about what to do next.

In this example, I’m going to create a simple counter with a simulated error to show what happens without an Error Boundary:

```

import { Component } from "react";
 
class Counter extends Component {
 
  state = {
    counter: 0,
  };
 
  handleClick = () => {
    this.setState({
      counter: this.state.counter + 1,
    });
  };
 
  render() {
    if (this.state.counter === 5) {
      // Simulate an error!
      throw new Error('I crashed!');
    }
    return (
      <div>
        <h1>{this.state.counter}</h1>
        <button onClick={this.handleClick}>+</button>
      </div>
    );
  }
}
 
export default Counter;
```


If you run this code as it is, once you increase the Counter after 5, the only thing you see is a blank page! For users, this is not ideal as they’re left confused about what to do next. With Error Boundaries, you can easily manage errors like this.

## Error Boundaries in React

Error boundaries only catch errors in the UI compartment of your code. This means that they only catch errors when they occur in these 3 places:

- In a lifecycle method
- During a render stage 
- Inside a constructor (e.g. inside your Hooks)

An Error Boundary will not be effective in:

- Event handlers (e.g. onClick, onChange)
- Asynchronous codes (e.g. requestAnimationFrame or setTimeout callbacks)
- Server-side rendering (SSR)
- Errors inside the Error Boundary itself

## How to Create Error Boundaries 

To create an Error Boundary, you first need to create a class component.

```
class ErrorBoundary extends Component {
```
Then you need to define a state variable that determines if the Error Boundary has caught an error or not.

```
state = {
    error: null,
  };
```
The class component should have at least three of these methods before it can function:

- A static getDerivedStateFromError: This is a lifecycle method that allows your Error Boundary to update its state and trigger a render that shows a fallback UI.

```
static getDerivedStateFromError(error) {
    return { error: error.};
  }
    // Updates state so the next render shows fallback UI.
```
The above code snippet allows you to display a more human-friendly error message to your user, rather than the blank page that is the effect of a broken component.

- A componentDidCatch: This is a lifecycle method that triggers certain operations when your Error Boundary does catch an error. For example, logging the error to an error logging service. 

```
componentDidCatch(error, info) {
   
  logErrorToExampleService (error, info);
}
// Logs error to an error reporting service
```

- A render method to show the fallback UI in case your Error Boundary catches an error.

```
 render() {
    if (this.state.error) {
      return (
        <p>
         Something Broke
        </p>
      )
    }
    return this.props.children
  }
// Renders any custom fallback UI
```
Best practices demand that you create a separate component to handle your Error Boundary instead of adding logic to catch errors directly into your code.

Now, let me modify these snippets to create an Error Boundary for my Counter “error”. 

```
import { Component } from "react";

class ErrorBoundary extends Component {
  state = {
    errorMessage: '',
  };

  static getDerivedStateFromError(error) {
    return { errorMessage: error.toString() };
  }

  componentDidCatch(error, info) {
    this.logErrorToServices(error.toString(), info.componentStack);
  }

  logErrorToServices = console.log;

  render() {
    if (this.state.errorMessage) {
      return (
        <p>
          {this.state.errorMessage}
        </p>
      )
    }
    return this.props.children
  }
}

export default ErrorBoundary
```
Finally, in App.js, wrap your Counter with the “error” inside the Error Boundary component so it catches it.

```
<ErrorBoundary>
     <Counter />
 </ErrorBoundary>
```
Don’t forget to import the Counter and Error Boundary components from their directories into your App.js. 

```
import Counter from "./Pages/Counter";
import ErrorBoundary from "./Components/ErrorBoundary";
```
Try running this code again by clicking the + button. You’ll see that once it reaches 5, instead of displaying the usual blank page, it will show the user-friendly error message and crash gracefully. 

## In Summary

Error Boundaries are great for providing a fallback UI that gives users feedback that something is wrong somewhere. The advantage is that it allows them to continue interacting with the webpage, even when something is broken. 

Instead of a blank page that doesn’t provide any means to navigate from that situation, they can either refresh or contact support for help.