React Error Boundaries: Catch JavaScript Errors Gracefully in Your UI

Last updated 3 months, 2 weeks ago | 271 views 75     5

Tags:- React

Introduction: Why React Error Boundaries Matter

We’ve all encountered it: a single component throws an error, and the entire app crashes. In large React applications, this can be a serious user experience issue. While JavaScript’s try/catch works for synchronous code, it doesn't catch rendering or lifecycle errors in React components.

That’s where React Error Boundaries come in.

An Error Boundary is a React component that catches JavaScript errors anywhere in its child component tree, logs those errors, and displays a fallback UI instead of breaking the whole app. This makes your React applications more resilient, stable, and user-friendly.


What Are React Error Boundaries?

Error Boundaries are special React components that catch errors in:

  • Render phase

  • Lifecycle methods

  • Constructors of child components

They do not catch errors in:

  • Event handlers

  • Asynchronous code (setTimeout, fetch, etc.)

  • Server-side rendering (SSR)


Key Methods of Error Boundaries

Method Purpose
static getDerivedStateFromError(error) Renders fallback UI
componentDidCatch(error, info) Logs error details

❗ You must use a class component to create an error boundary (as of React 18). Hooks-based error boundaries are not yet supported.


How to Create an Error Boundary in React (Step-by-Step)

1. Create a Class Component

import React from 'react';

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  // Update state to show fallback UI
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  // Log error details (you could log to an external service)
  componentDidCatch(error, errorInfo) {
    console.error("Caught by Error Boundary:", error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <h2>Something went wrong.</h2>;
    }

    return this.props.children;
  }
}

export default ErrorBoundary;

2. Wrap Components with the Error Boundary

import ErrorBoundary from './ErrorBoundary';
import ProblematicComponent from './ProblematicComponent';

function App() {
  return (
    <div>
      <h1>My React App</h1>
      <ErrorBoundary>
        <ProblematicComponent />
      </ErrorBoundary>
    </div>
  );
}

3. Simulate an Error

function ProblematicComponent() {
  throw new Error("Oops! Something went wrong.");
  return <div>This will never render.</div>;
}

✅ Result: The app doesn’t crash. Instead, it shows the fallback UI:
"Something went wrong."


Complete Functional Example: React Error Boundary in Action

// ErrorBoundary.js
import React from 'react';

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    console.log("Error log:", error, info);
  }

  render() {
    if (this.state.hasError) {
      return <div style={{ color: 'red' }}>Oops! Something went wrong.</div>;
    }

    return this.props.children;
  }
}

export default ErrorBoundary;
// BuggyComponent.js
import React from 'react';

function BuggyComponent() {
  throw new Error("Crash!");
  return <div>This will not render</div>;
}

export default BuggyComponent;
// App.js
import React from 'react';
import ErrorBoundary from './ErrorBoundary';
import BuggyComponent from './BuggyComponent';

function App() {
  return (
    <div>
      <h1>Demo: React Error Boundaries</h1>
      <ErrorBoundary>
        <BuggyComponent />
      </ErrorBoundary>
    </div>
  );
}

export default App;

Tips & Common Pitfalls

Best Practices

  • Wrap isolated sections of your UI to prevent full-app crashes.

  • Use custom fallback UI to improve user experience.

  • Log errors to remote services like Sentry or LogRocket for visibility.

  • Combine Error Boundaries with lazy loading and Suspense for even smoother failover.

Common Mistakes

  • Expecting Error Boundaries to catch async or event handler errors (they won’t).

  • Forgetting to reset hasError when users retry.

  • Using functional components instead of class-based ones (not supported).

  • Wrapping the entire app in one global Error Boundary (leads to a poor fallback experience).


Comparison: Error Handling Methods in React

Technique Catches Render Errors Catches Async Errors Reusable UI Fallback
try/catch
Error Boundary
window.onerror ✅ (limited) ✅ (limited)

Conclusion: Build Resilient UIs with Error Boundaries

React Error Boundaries are essential for gracefully handling rendering errors and keeping your app from completely crashing when something goes wrong. They let you display user-friendly fallback UIs and maintain the integrity of your app.

Takeaways

  • Use class-based components for error boundaries.

  • Catch and handle UI-level errors during rendering.

  • Display custom fallback UIs to guide users.

  • Log errors to external monitoring tools for diagnostics.

  • Combine with route-based or feature-based boundaries for flexibility.