Skip to main content
The ErrorBoundary component catches JavaScript errors anywhere in the component tree, logs errors, and displays a fallback UI instead of crashing the entire app.

When to Use

  • Prevent entire app crashes from component errors
  • Display user-friendly error messages
  • Provide recovery mechanisms (retry buttons)
  • Log errors for monitoring and debugging
  • Isolate errors to specific parts of the UI

Basic Usage

import { ErrorBoundary } from "@zayne-labs/ui-react/common/error-boundary";

function App() {
  return (
    <ErrorBoundary fallback={<div>Something went wrong</div>}>
      <MyComponent />
    </ErrorBoundary>
  );
}

Component API

children
React.ReactNode
required
Components to wrap with error boundary protection
fallback
React.ReactNode | ((props: ErrorFallbackProps) => React.ReactNode)
UI to display when an error is caught. Can be a static component or render function
onError
(context: { error: Error; info: React.ErrorInfo }) => void
Callback fired when an error is caught. Useful for error logging services
onReset
(context: ResetContext) => void
Callback fired when the error boundary is reset, either imperatively or via resetKeys
resetKeys
unknown[]
Array of values that will reset the error boundary when they change. Useful for resetting on prop/state changes

ErrorFallbackProps

error
Error
The error that was caught
resetErrorBoundary
(...args: unknown[]) => void
Function to reset the error boundary and re-render children

Examples

Error Logging

import { ErrorBoundary } from "@zayne-labs/ui-react/common/error-boundary";

function App() {
  const handleError = ({ error, info }) => {
    // Send to error monitoring service
    console.error("Error caught:", error);
    console.error("Component stack:", info.componentStack);

    // Example: Send to Sentry
    // Sentry.captureException(error, { contexts: { react: info } });
  };

  return (
    <ErrorBoundary
      onError={handleError}
      fallback={({ error }) => (
        <div>
          <h1>Oops! Something went wrong</h1>
          <details>
            <summary>Error details</summary>
            <pre>{error.message}</pre>
          </details>
        </div>
      )}
    >
      <App />
    </ErrorBoundary>
  );
}

Auto-Reset on Key Change

import { ErrorBoundary } from "@zayne-labs/ui-react/common/error-boundary";

function UserProfile({ userId }) {
  return (
    <ErrorBoundary
      resetKeys={[userId]}
      fallback={({ error, resetErrorBoundary }) => (
        <div>
          <p>Failed to load user: {error.message}</p>
          <button onClick={resetErrorBoundary}>Retry</button>
        </div>
      )}
    >
      <UserData userId={userId} />
    </ErrorBoundary>
  );
}
When userId changes, the error boundary automatically resets and re-renders the children.

Nested Error Boundaries

import { ErrorBoundary } from "@zayne-labs/ui-react/common/error-boundary";

function Dashboard() {
  return (
    <div>
      <ErrorBoundary fallback={<div>Header failed to load</div>}>
        <Header />
      </ErrorBoundary>

      <ErrorBoundary fallback={<div>Sidebar failed to load</div>}>
        <Sidebar />
      </ErrorBoundary>

      <ErrorBoundary
        fallback={({ error, resetErrorBoundary }) => (
          <div>
            <p>Main content error: {error.message}</p>
            <button onClick={resetErrorBoundary}>Reload</button>
          </div>
        )}
      >
        <MainContent />
      </ErrorBoundary>
    </div>
  );
}

Using the Hook

import { useErrorBoundary } from "@zayne-labs/ui-react/common/error-boundary";

function DataFetcher() {
  const { showBoundary, resetBoundary } = useErrorBoundary();
  const [data, setData] = useState(null);

  const fetchData = async () => {
    try {
      const response = await fetch("/api/data");
      if (!response.ok) throw new Error("Failed to fetch");
      const json = await response.json();
      setData(json);
    } catch (error) {
      showBoundary(error);
    }
  };

  return (
    <div>
      <button onClick={fetchData}>Load Data</button>
      {data && <pre>{JSON.stringify(data, null, 2)}</pre>}
    </div>
  );
}

function App() {
  return (
    <ErrorBoundary fallback={({ error, resetErrorBoundary }) => (
      <div>
        <p>Error: {error.message}</p>
        <button onClick={resetErrorBoundary}>Reset</button>
      </div>
    )}>
      <DataFetcher />
    </ErrorBoundary>
  );
}

Custom Error UI

import { ErrorBoundary } from "@zayne-labs/ui-react/common/error-boundary";

function ErrorFallback({ error, resetErrorBoundary }) {
  return (
    <div className="error-container">
      <div className="error-icon">⚠️</div>
      <h2>Something unexpected happened</h2>
      <p className="error-message">{error.message}</p>
      <div className="error-actions">
        <button onClick={resetErrorBoundary} className="btn-primary">
          Try Again
        </button>
        <button onClick={() => window.location.href = '/'} className="btn-secondary">
          Go Home
        </button>
      </div>
    </div>
  );
}

function App() {
  return (
    <ErrorBoundary fallback={ErrorFallback}>
      <MyApp />
    </ErrorBoundary>
  );
}

Comparison to Native Patterns

Class Component Error Boundary

class ErrorBoundary extends React.Component {
  state = { hasError: false, error: null };

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

  componentDidCatch(error, info) {
    console.error(error, info);
  }

  render() {
    if (this.state.hasError) {
      return <div>Error: {this.state.error.message}</div>;
    }
    return this.props.children;
  }
}

With Zayne Labs ErrorBoundary

import { ErrorBoundary } from "@zayne-labs/ui-react/common/error-boundary";

<ErrorBoundary
  onError={({ error, info }) => console.error(error, info)}
  fallback={({ error }) => <div>Error: {error.message}</div>}
>
  {children}
</ErrorBoundary>

Common Use Cases

Protecting Route Components

import { ErrorBoundary } from "@zayne-labs/ui-react/common/error-boundary";

function RouteErrorFallback({ error, resetErrorBoundary }) {
  return (
    <div className="route-error">
      <h1>Page Error</h1>
      <p>{error.message}</p>
      <button onClick={resetErrorBoundary}>Reload Page</button>
    </div>
  );
}

function Router() {
  return (
    <Routes>
      <Route
        path="/"
        element={
          <ErrorBoundary fallback={RouteErrorFallback}>
            <HomePage />
          </ErrorBoundary>
        }
      />
      <Route
        path="/profile"
        element={
          <ErrorBoundary fallback={RouteErrorFallback}>
            <ProfilePage />
          </ErrorBoundary>
        }
      />
    </Routes>
  );
}

Form Validation Errors

import { ErrorBoundary } from "@zayne-labs/ui-react/common/error-boundary";

function FormContainer() {
  return (
    <ErrorBoundary
      fallback={({ error, resetErrorBoundary }) => (
        <div className="form-error">
          <p>Form submission failed: {error.message}</p>
          <button onClick={resetErrorBoundary}>Try Again</button>
        </div>
      )}
    >
      <ComplexForm />
    </ErrorBoundary>
  );
}
This component is based on the react-error-boundary package with enhanced TypeScript support.
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

Build docs developers (and LLMs) love