DEV Community

Cover image for Mastering Error Boundaries in React: Why & How 🚨
mohiyaddeen7
mohiyaddeen7

Posted on

Mastering Error Boundaries in React: Why & How 🚨

Why Use Error Boundaries?

Why Use Error Boundaries?

React applications, like any software, are prone to runtime errors—especially in production. Errors can cause parts of your app to crash, disrupting the user experience. React’s Error Boundaries let you catch these errors gracefully, allowing you to handle them without bringing down the entire application.

Since React 16, Error Boundaries have helped developers capture errors in the component tree and provide fallback UIs, making your app more resilient.

What Are Error Boundaries? 🤔

By default, if your application throws an error during rendering, React will remove its UI from the screen. To prevent this, you can wrap a part of your UI into an error boundary. Error Boundaries are special components that catch JavaScript errors in their child component tree, log them, and display a fallback UI. They prevent the error from “bubbling up” and crashing the entire app. However, they only catch errors in lifecycle methods, render methods, and constructors of child components.

Creating an Error Boundary

To create an Error Boundary, define a class component with two lifecycle methods:

  • static getDerivedStateFromError(error): Update state when an error is caught.
  • componentDidCatch(error, info): Log the error.

Example Implementation :

import React, { Component } from 'react';

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

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // Log the error to an error reporting service
    console.error("Error caught in ErrorBoundary:", error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // Render a fallback UI
      return <h1>Oops! Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

export default ErrorBoundary;

Enter fullscreen mode Exit fullscreen mode

Example Usage :

import React, { useState, useEffect } from 'react';
import ErrorBoundary from './ErrorBoundary';

function UserProfile() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    // Simulating an error (e.g., a failed API request)
    throw new Error("User data failed to load!");
  }, []);

  return <div>{user ? user.name : "Loading..."}</div>;
}

function App() {
  return (
    <ErrorBoundary>
      <UserProfile />
    </ErrorBoundary>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

In this example:

  • If UserProfile throws an error (like an error from useEffect), the Error Boundary will catch it and render the fallback UI. **

Real-World Scenario 🌍

Imagine you have a dashboard component that displays user data. Occasionally, the API may fail, causing your UserProfile component to throw an error. By wrapping it in ErrorBoundary, you ensure that a friendly message is shown while you troubleshoot the issue.

Limitations:

  • Error Boundaries don't catch errors in event handlers, asynchronous code (like promises), or in code that happens outside the rendering lifecycle.
  • If you want to catch errors inside event handlers or asynchronous code in functional components, you would need to wrap those specific operations in try-catch blocks or use a different error handling method (e.g., error boundaries for asynchronous code).

Wrapping Up

Error Boundaries provide a safety net for handling unexpected errors, letting you manage and recover gracefully. Try adding them around crucial components, especially where data is fetched or critical features are rendered.


Let's connect on LinkedIn 🚀

Happy coding✌🏻

Please don't hesitate to ask doubts in the comments section—I'll be sure to respond promptly. Your inquiries are greatly welcomed and will receive a swift and thorough reply.❤️

Top comments (0)