> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appsignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# AppSignal for Browser with React

<Note>
  Browser monitoring is a beta [AppSignal Labs](/labs) feature. The
  `@appsignal/browser` package is published under the `beta` tag on npm, and its
  configuration and API may still change between beta releases. Share feedback
  in our [Discord community](https://discord.gg/EjF6ykYx63).
</Note>

React swallows errors thrown during rendering: instead of reaching `window`, they unmount the tree. An error boundary is the only way to see them. AppSignal for Browser ships one as a subpath export of the package, so there is nothing extra to install.

**Optional**: React 16.8 or later, if you want to use the error boundary shipped with the package.

## Catching render errors

<CodeGroup>
  ```jsx JSX theme={null}
  import { captureError } from "@appsignal/browser";
  import { ErrorBoundary } from "@appsignal/browser/react";

  <ErrorBoundary
    captureError={captureError}
    fallback={<p>Something went wrong.</p>}
  >
    <App />
  </ErrorBoundary>
  ```
</CodeGroup>

`captureError` is passed as a prop rather than imported by the boundary itself, so the same component works for both the ES module and the UMD build.

Errors caught this way arrive with the name of the component that threw, and the full list of components it was nested inside at the time. That is usually enough to find the problem without reproducing it.

### Recovering from an error

Pass a function as `fallback` to give the user a way to try again. It receives the error and a `reset` function, which clears the error and renders the children again:

<CodeGroup>
  ```jsx JSX theme={null}
  <ErrorBoundary
    captureError={captureError}
    fallback={(error, reset) => (
      <div>
        <p>{error.message}</p>
        <button onClick={reset}>Try again</button>
      </div>
    )}
  >
    <Dashboard />
  </ErrorBoundary>
  ```
</CodeGroup>

### Wrapping a single component

`withErrorBoundary` wraps one component, which is convenient for widgets that should fail without taking the page down:

<CodeGroup>
  ```jsx JSX theme={null}
  import { captureError } from "@appsignal/browser";
  import { withErrorBoundary } from "@appsignal/browser/react";

  const SafeRevenueWidget = withErrorBoundary(RevenueWidget, {
    captureError,
    fallback: <p>This widget is unavailable.</p>,
  });
  ```
</CodeGroup>

### Props

| Prop           | Type                              | Description                                                      |
| -------------- | --------------------------------- | ---------------------------------------------------------------- |
| `captureError` | `function`                        | Required. The `captureError` function from `@appsignal/browser`. |
| `fallback`     | node or `(error, reset) => node`  | What to render after an error. Renders nothing when omitted.     |
| `onError`      | `(error, componentStack) => void` | Called before the error is sent to AppSignal.                    |

Place boundaries where a failure has a sensible fallback: around each route, and around individual widgets that can be missing without breaking the page. One boundary at the root catches everything, but replaces your whole application with the fallback.

## Reporting the current route

[Report the current route](/browser/installation#report-the-current-route) on every navigation, using the template such as `/orders/:id` rather than the resolved path.

<CodeGroup>
  ```jsx React Router theme={null}
  import { useEffect } from "react";
  import { useMatches } from "react-router";
  import { setRouteTemplate } from "@appsignal/browser";

  function RouteReporter() {
    const matches = useMatches();

    useEffect(() => {
      const route = matches.at(-1);
      if (route) setRouteTemplate(route.id);
    }, [matches]);

    return null;
  }
  ```

  ```jsx Next.js App Router theme={null}
  "use client";

  import { useEffect } from "react";
  import { usePathname } from "next/navigation";
  import { setRouteTemplate } from "@appsignal/browser";

  export function RouteReporter() {
    const pathname = usePathname();

    useEffect(() => {
      setRouteTemplate(pathname);
    }, [pathname]);

    return null;
  }
  ```

  ```jsx Next.js Pages Router theme={null}
  import { useEffect } from "react";
  import { useRouter } from "next/router";
  import { setRouteTemplate } from "@appsignal/browser";

  export function RouteReporter() {
    const { pathname } = useRouter();

    useEffect(() => {
      setRouteTemplate(pathname); // e.g. "/orders/[id]"
    }, [pathname]);

    return null;
  }
  ```
</CodeGroup>

<Note>
  Import your AppSignal setup before your router. The SDK and most routers both
  patch `history.pushState`, and the SDK composes with an existing patch rather
  than replacing it. Loading the router first can leave client-side navigation
  unreported.
</Note>

## Reporting errors from event handlers and effects

An error boundary catches errors thrown during rendering. It does not catch errors thrown in an event handler, a `setTimeout`, or a rejected promise inside an effect. Uncaught ones reach `window` and are reported automatically. For the rest, report them yourself:

<CodeGroup>
  ```jsx JSX theme={null}
  import { captureError } from "@appsignal/browser";

  async function onSubmit(order) {
    try {
      await submitOrder(order);
    } catch (error) {
      captureError(error, { orderId: order.id });
      setStatus("failed");
    }
  }
  ```
</CodeGroup>
