Skip to content

Understanding ErrorBoundary in React: A Comprehensive Guide

Understanding ErrorBoundary in React: A Comprehensive Guide

Hello my name is Luiz and in this Article we are going to cover how Error Boundaries work in React

Error Boundaries are a powerful feature in React that allow you to catch JavaScript errors anywhere in your component tree, log those errors, and display a fallback UI instead of crashing the entire application. Let's dive into how they work by examining a practical implementation.

What Are Error Boundaries?

Error Boundaries are React components that catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them. They act as a safety net for your application, preventing a single component failure from breaking your entire UI.

The Implementation

Here's the ErrorCatcher component that demonstrates this pattern:

import { ErrorInfo, PureComponent, ReactNode } from "react";

type ErrorBoundaryState = {
  hasError: boolean;
};

type ErrorBoundaryProps = {
  onBoundaryError: (error: Error, errorInfo: ErrorInfo) => void;
  fallback: ReactNode;
};

class ErrorCatcher extends PureComponent<
  ErrorBoundaryProps,
  ErrorBoundaryState
> {
  constructor(props: ErrorBoundaryProps) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error: Error) {
    return { hasError: true, error };
  }

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    this.props.onBoundaryError?.(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      if (!this.props.fallback) {
        return null;
      }
      return this.props.fallback;
    }
    return this.props.children;
  }
}

function ExampleError(): JSX.Element {
  throw new Error("Example error");
}

function Root() {
  return (
    <ErrorCatcher
      fallback={<div>Something went wrong!</div>}
      onBoundaryError={(error, errorInfo) => {
        console.error("Error caught:", error, errorInfo);
        // Send to error tracking service
      }}
    >
      <ExampleError />
    </ErrorCatcher>
  );
}

Breaking Down the Code

State Initialization constructor

The component maintains a simple state to track whether an error has occurred:

this.state = { hasError: false };

This boolean flag determines whether to render the normal content or the fallback UI.

getDerivedStateFromError

This static lifecycle method is called when a descendant component throws an error:

static getDerivedStateFromError(error: Error) {
  return { hasError: true, error };
}

Key characteristics:

  • Called during the render phase
  • Must be a pure function
  • Updates state to trigger a re-render with fallback UI
  • Receives the error as a parameter

componentDidCatch

This method is called after an error has been thrown:

componentDidCatch(error: Error, errorInfo: ErrorInfo) {
  this.props.onBoundaryError?.(error, errorInfo);
}

Purpose:

  • Called during the commit phase
  • Allows side effects like error logging
  • Receives both the error and additional error information
  • Perfect for sending error reports to monitoring services

Render Logic

The render method implements the fallback behavior:

render() {
  if (this.state.hasError) {
    if (!this.props.fallback) {
      return null;
    }
    return this.props.fallback;
  }
  return this.props.children;
}

Flow:

  1. If an error occurred, check for a fallback component
  2. If no fallback is provided, render nothing (null)
  3. If a fallback exists, render it
  4. Otherwise, render the children normally

Usage Example

<ErrorCatcher
  fallback={<div>Something went wrong!</div>}
  onBoundaryError={(error, errorInfo) => {
    console.error("Error caught:", error, errorInfo);
    // Send to error tracking service
  }}
>
  <YourComponent />
</ErrorCatcher>

What Error Boundaries Don't Catch

It's important to note that Error Boundaries do not catch errors in:

  • Event handlers (use try-catch instead)
  • Asynchronous code (setTimeout, promises)
  • Server-side rendering
  • Errors thrown in the Error Boundary itself

Best Practices

Strategic Placement: Place Error Boundaries at key points in your component tree. You might have one at the top level and others around specific features.

Meaningful Fallbacks: Provide user-friendly error messages that explain what went wrong and what users can do next.

Error Logging: Always implement the onBoundaryError callback to track errors in production.

Granular Boundaries: Don't wrap everything in a single Error Boundary. Use multiple boundaries to isolate failures and keep unaffected parts of your UI functional.

Development vs Production: Show detailed error information in development but user-friendly messages in production.

Advantages of This Implementation

Flexibility: The optional fallback prop allows different fallback UIs for different contexts.

Extensibility: The onBoundaryError callback enables custom error handling logic.

Performance: Extends PureComponent for optimized re-renders.

Type Safety: Uses TypeScript for compile-time type checking.

Conclusion

Error Boundaries are an essential tool for building resilient React applications. The ErrorCatcher implementation shown here provides a clean, reusable way to handle errors gracefully, improving user experience and making debugging easier. By catching errors at the component level, you can prevent entire application crashes and maintain a smooth user experience even when things go wrong.

Profile picture
Luiz Fernando - Senior Software Engineer

Thanks for reading!

I hope you enjoyed reading this article. If you have any questions or feedback, don't hesitate to reach out to me on my social media bellow. Have a great day!

Carousel imageCarousel imageCarousel imageCarousel imageCarousel image
Next / Something good starts with a conversation

Big ideas.
Little Luiz.

A product to bring to life? A team to make stronger? Let’s find out what we can build together.

Pick your path
01Freelance / Products

I have a project

Freelance collaborations, products, and technical challenges.

  • From product discovery to delivery
  • Web, mobile, and backend engineering
  • Clear scope. Direct collaboration.
Let’s build something
02Hiring / Teams

I’m building a team

Engineering roles and long-term opportunities.

  • Senior full-stack engineering
  • Product thinking and technical ownership
  • Experience with distributed teams
Hire me for your team
03Résumé / Versions

Explore résumés

Tailored versions for general engineering, health-tech, fintech, and more.

  • Six focused variants
  • Print-ready PDF export
  • Updated for every role
Read my résumé
luizepauloxd@gmail.com

Prefer email? Write directly, or start a draft here.

Tell me what you have in mind.

© 2026 Luiz Fernando Made with intention. And a little curiosity.Back to top