Skip to main content
react-md

ErrorBoundary

The ErrorBoundary component can be used to catch run-time errors in the app by displaying fallback content when an error is thrown. The ErrorBoundary is a minimal fork of the react-error-boundary package that only includes things I consider useful. Use the react-error-boundary if more complex behavior is required.

Simple Example

The ErrorBoundary is a client component and requires fallback (any ReactNode) content to be displayed.

The example below shows how the error boundary can catch run-time errors and display the fallback content without crashing the entire app. The demo must be reset to try again.

"use client";

import { Button } from "@react-md/core/button/Button";
import { ErrorBoundary } from "@react-md/core/error-boundary/ErrorBoundary";
import { useToggle } from "@react-md/core/useToggle";
import { type ReactElement } from "react";

export default function SimpleExample(): ReactElement {
  return (
    <ErrorBoundary fallback={<span>Fallback!</span>}>
      <ErrorAfterClick />
    </ErrorBoundary>
  );
}

function ErrorAfterClick(): ReactElement {
  const { toggle, toggled } = useToggle();

  if (toggled) {
    throw new Error("Unable to render");
  }

  return (
    <Button onClick={toggle} theme="error" themeType="contained">
      Cause Error
    </Button>
  );
}

Press Enter to start editing.

Resettable Example

To help with cases where the app can be recovered after an error, the ErrorBoundary can also be reset using the useErrorBoundary hook in the fallback content. The hook returns an object with:

The errored flag should always be true when this hook is called from the fallback component and will assert the error is an Error.

"use client";

import { Button } from "@react-md/core/button/Button";
import { ErrorBoundary } from "@react-md/core/error-boundary/ErrorBoundary";
import { useErrorBoundary } from "@react-md/core/error-boundary/useErrorBoundary";
import { Typography } from "@react-md/core/typography/Typography";
import { useToggle } from "@react-md/core/useToggle";
import { type ReactElement } from "react";

export default function ResettableExample(): ReactElement {
  return (
    <ErrorBoundary fallback={<ResettableFallback />}>
      <ErrorAfterClick />
    </ErrorBoundary>
  );
}

function ErrorAfterClick(): ReactElement {
  const { toggle, toggled } = useToggle();

  if (toggled) {
    throw new Error("Unable to render");
  }

  return (
    <Button onClick={toggle} theme="error" themeType="contained">
      Cause Error
    </Button>
  );
}

// it isn't shown by default since the error/stacktrace isn't quite useful in these runnable demos
const SHOW_ERROR_MESSAGE = false;

function ResettableFallback(): ReactElement | null {
  const { error, errored, reset } = useErrorBoundary();
  if (!errored) {
    // this isn't possible from this flow as the `ResettableFallback` will
    // only be mounted once there is an error
    return null;
  }

  return (
    <>
      <Typography textColor="error">There was an error!</Typography>
      {SHOW_ERROR_MESSAGE && (
        <pre className="language-sh code-block code-block__pre">
          <code className="language-sh">{error.stack ?? error.message}</code>
        </pre>
      )}
      <Button onClick={reset}>Try Again</Button>
    </>
  );
}

Press Enter to start editing.