Blog>
Snippets

Using Error Boundaries with Hooks

Implement a custom hook for error handling within functional components and demonstrate how to use it along with an Error Boundary.
import { useState, useCallback } from 'react';

// Custom hook to manage errors
function useErrorBoundary() {
  const [error, setError] = useState(null);

  const throwError = useCallback((error) => {
    setError(error);
  }, []);

  // Reset error state
  const resetError = useCallback(() => {
    setError(null);
  }, []);

  return { error, throwError, resetError };
}
This piece of code defines a custom hook called useErrorBoundary which is designed to handle errors within functional components. It uses useState to keep track of any errors and provides two functions, throwError to set an error and resetError to reset the error state.
import React from 'react';

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

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

  componentDidCatch(error, errorInfo) {
    // You can log the error to an error reporting service
  }

  reset = () => {
    this.setState({ hasError: false });
    // Optionally reset other state or props
  };

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <div>An error has occurred</div>
    }

    return this.props.children;
  }
}
This piece of code creates an ErrorBoundary class component. It captures errors in any child components and changes its internal state to render a fallback UI instead of the component tree that crashed. It also includes a reset method to clear the error and allow for recovery.
import React from 'react';
import { useErrorBoundary } from './useErrorBoundary'; // Import custom hook

// Example of a component which might throw an error
function MyComponent() {
  const { error, throwError, resetError } = useErrorBoundary();

  if (error) {
    return (
      <div>
        <p>An error has been caught: {error.message}</p>
        <button onClick={resetError}>Try Again</button>
      </div>
    );
  }

  // Function that could potentially cause an error
  const doSomethingRisky = () => {
    try {
      // Risky behavior
    } catch (err) {
      throwError(err);
    }
  };

  return (
    <div>
      <button onClick={doSomethingRisky}>Do Something Risky</button>
    </div>
  );
}
This piece of code shows how to use the useErrorBoundary hook inside a functional component called MyComponent. It attempts to perform a risky operation within a try-catch block. If an error is caught, it calls throwError from the custom hook to handle the error. If there's an error state, it renders an error message and a button to reset the error. Otherwise, it renders the UI as normal with a button to perform the risky operation.