Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 21 additions & 49 deletions docs/platforms/javascript/guides/react/features/react-router/v6.mdx
Original file line number Diff line number Diff line change
@@ -1,41 +1,19 @@
---
title: React Router v6
description: "Learn about Sentry's React Router v6 integration."
description: "Learn how to instrument your React Router v6 application with Sentry."
sidebar_order: 20
---

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to lead with something like this:

Suggested change
You can instrument your React Router v6 setup with Sentry. Depending on how you use react-router, slightly different setups are needed:
<TableOfContents ignoreIds={["custom-error-boundary", "next-steps"]} />
Additionally, make sure to [Setup a Custom Error Boundary](#custom-error-boundary) to ensure rendering errors are captured to Sentry.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and something similar for react-router v7 :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mydea Good point! I updated the start of the page with an adapted version of your suggestion.

Sadly, the TableOfContents component does not work with our structure as it seems to be created to work with the SDK options pages, and our structure here is quite different -> I created an issue #13159 so we can consider upgrading the functionality of this component

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be fixed here #13171 😅

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the toc is now included - looks good!

<Alert>
- React Router v6 support is included in the `@sentry/react` package since
version `7`.
</Alert>

Update your `Sentry.browserTracingIntegration` to `Sentry.reactRouterV6BrowserTracingIntegration` and provide the required React hooks and router functions:

- `useEffect` hook from `react`
- `useLocation` and `useNavigationType` hooks from `react-router-dom` or `react-router`
- `createRoutesFromChildren` and `matchRoutes` functions from `react-router-dom` or `react-router`

<Alert level="warning">

To ensure proper routing instrumentation, initialize Sentry by calling `Sentry.init` **before**:

- Wrapping your `<Routes />` component
- Using `useRoutes`
- Using `wrapCreateBrowserRouterV6` or `wrapCreateMemoryRouterV6`

</Alert>
Apply the following setup steps based on your routing method and create a [custom error boundary](#set-up-a-custom-error-boundary) to make sure Sentry automatically captures rendering errors:

### Usage with `createBrowserRouter` or `createMemoryRouter`
<TableOfContents ignoreIds={["set-up-a-custom-error-boundary", "next-steps"]} />

If you choose to create your router instance with [`createBrowserRouter`](https://reactrouter.com/en/main/routers/create-browser-router) or [`createMemoryRouter`](https://reactrouter.com/en/main/routers/create-memory-router), you can use `Sentry.wrapCreateBrowserRouterV6` or `Sentry.wrapCreateMemoryRouterV6` to wrap it with the instrumentation:
## Usage with `createBrowserRouter` or `createMemoryRouter`

<Alert level="warning" title="Note">
To instrument your React Router, update your `Sentry.browserTracingIntegration` to `Sentry.reactRouterV6BrowserTracingIntegration` within `Sentry.init` and provide the required React hooks and router functions. Then, wrap the router instance created by `createBrowserRouter` or `createMemoryRouter` with one of the following functions:

`wrapCreateMemoryRouterV6` was introduced in SDK version 8.50.0. Prior to that version, we suggested using `wrapCreateBrowserRouterV6` with `createMemoryRouter`. If you are currently using `wrapCreateBrowserRouterV6` to wrap `createMemoryRouter`, it is recommended that you use `wrapCreateMemoryRouterV6` instead.

You can instrument [`createHashRouter`](https://reactrouter.com/en/main/routers/create-hash-router) using the `wrapCreateBrowserRouterV6` function.

</Alert>
- Use `Sentry.wrapCreateBrowserRouterV6` for [`createBrowserRouter`](https://reactrouter.com/en/main/routers/create-browser-router) and [`createHashRouter`](https://reactrouter.com/en/main/routers/create-hash-router)
- Use `Sentry.wrapCreateMemoryRouterV6` for [`createMemoryRouter`](https://reactrouter.com/en/main/routers/create-memory-router) (introduced in SDK version `8.50.0`)

```javascript {2-8, 15-21, 26-33}
import React from "react";
Expand Down Expand Up @@ -71,9 +49,9 @@ const router = sentryCreateBrowserRouter([
]);
```

### Usage With `<Routes />` Component
## Usage With `<Routes />` Component

If you're using the `<Routes />` component to define your routes, wrap [`Routes`](https://reactrouter.com/en/main/components/routes) using `Sentry.withSentryReactRouterV6Routing`. This creates a higher order component, which will enable Sentry to reach your router context. You can also use `Sentry.withSentryReactRouterV6Routing` for `Routes` inside `BrowserRouter`. `MemoryRouter`, and `HashRouter` components:
If you're using the `<Routes />` component to define your routes, update your `Sentry.browserTracingIntegration` to `Sentry.reactRouterV6BrowserTracingIntegration` inside `Sentry.init` and provide the required React hooks and router functions. Then, wrap `<Routes />` using `Sentry.withSentryReactRouterV6Routing`. This creates a higher order component, which will enable Sentry to reach your router context. You can also use `Sentry.withSentryReactRouterV6Routing` for routes inside `BrowserRouter`, `MemoryRouter`, and `HashRouter` components.

```javascript {3-11, 18-24, 29, 33-35}
import React from "react";
Expand Down Expand Up @@ -115,19 +93,16 @@ ReactDOM.render(
);
```

This is only needed at the top level of your app, rather than how v4/v5 required wrapping every `<Route/>` you wanted parametrized.
This wrapper is only needed at the top level of your app, unlike React Router v4/v5, which required wrapping every `<Route />` you wanted parametrized.

### Usage With `useRoutes` Hook
## Usage With `useRoutes` Hook

<Alert>
Available in `@sentry/react` version `7.12.1` and above.
</Alert>
_Available in `@sentry/react` version `7.12.1` and above._

If you specify your route definitions as an object to the [`useRoutes` hook](https://reactrouter.com/en/main/hooks/use-routes), use `Sentry.wrapUseRoutesV6` to create a patched `useRoutes` hook that instruments your routes with Sentry.
If you specify your route definitions as an object to the [`useRoutes` hook](https://reactrouter.com/en/main/hooks/use-routes), update your `Sentry.browserTracingIntegration` to `Sentry.reactRouterV6BrowserTracingIntegration` inside `Sentry.init` and provide the required React hooks and router functions. Then, use `Sentry.wrapUseRoutesV6` to create a patched `useRoutes` hook that instruments your routes with Sentry.

<Alert level="warning">

`wrapUseRoutesV6` should be called outside of a React component, as in the example below. It's also recommended that you assign the wrapped hook to a variable name starting with `use`, as per the [React documentation](https://reactjs.org/docs/hooks-custom.html#extracting-a-custom-hook).
<Alert level="warning" title="Important">
Call `wrapUseRoutesV6` outside of a React component, as in the example below. We also recommend that you assign the wrapped hook to a variable starting with `use`, as per [React's documentation](https://react.dev/learn/reusing-logic-with-custom-hooks#hook-names-always-start-with-use).

</Alert>

Expand Down Expand Up @@ -173,16 +148,13 @@ ReactDOM.render(
);
```

Now, Sentry should generate `pageload`/`navigation` transactions with parameterized transaction names (for example, `/teams/:teamid/user/:userid`), where applicable. This is only needed at the top level of your app, rather than how v4/v5 required wrapping every `<Route/>` you wanted parametrized.

### Custom Error Boundaries
Now, Sentry should generate `pageload`/`navigation` transactions with parameterized transaction names (for example, `/teams/:teamid/user/:userid`), where applicable. This is only needed at the top level of your app, unlike React Router v4/v5, which required wrapping every `<Route />` you wanted parametrized.

When using `react-router`, errors thrown inside route elements will only be re-thrown in **development mode** while using [`strict mode`](https://react.dev/reference/react/StrictMode). In production, these errors won't be surfaced unless manually captured. If you **don't** have a custom error boundary in place, `react-router` will create a default one that "swallows" all errors.
## Set Up a Custom Error Boundary

<Alert>
Note, that this only applies to render method and lifecycle errors since React
doesn't need error boundaries to handle errors in event handlers.
</Alert>
When using `react-router`, errors thrown inside route elements will only be re-thrown in **development mode** while using [`strict mode`](https://react.dev/reference/react/StrictMode).\
In production, these errors won't surface unless captured manually. If you **don't** have a custom error boundary in place, `react-router` will create a default one that "swallows" all errors.\
Hence, to capture these errors with Sentry in production, we strongly recommend to implement a custom error boundary.

To send errors to Sentry while using a custom error boundary, use the `Sentry.captureException` method:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to any change in this PR but generally: We should clarify here, because it is not clear to me: What If I am not using a custom error boundary, what should I do then? Should I add one to capture errors, or not? cc @lforst & @AbhiPrasad

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for react router you need to add one, otherwise component-related errors get swallowed by the router itself.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, so let's reword this (can be a different PR as well) to make it clear you def should add this, not just if you're using a custom boundary!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a sentence to the first paragraph in this section (v6 and v7 pages) -- hope this is what you meant (if not, let's chat later today @mydea :) )


Expand Down Expand Up @@ -226,7 +198,7 @@ export function YourCustomRootErrorBoundary() {

```

## Next Steps:
## Next Steps

- [Return to **Getting Started**](../../)
- [Return to the main integrations page](../)
75 changes: 25 additions & 50 deletions docs/platforms/javascript/guides/react/features/react-router/v7.mdx
Original file line number Diff line number Diff line change
@@ -1,46 +1,25 @@
---
title: React Router v7 (library mode)
description: "Learn about Sentry's React Router v7 integration."
description: "Learn how to instrument your React Router v7 application with Sentry."
sidebar_order: 10
---


<Alert level="warning" title="Looking for framework mode?">
- React Router v7 (framework mode) is currently in experimental Alpha, check out the docs [here](/platforms/javascript/guides/react-router/).
</Alert>

<Alert level="info">
React Router v7 (library mode) support is included in the `@sentry/react`
package since version `8.42.0`.
</Alert>

Update your `Sentry.browserTracingIntegration` to `Sentry.reactRouterV7BrowserTracingIntegration` and provide the required React hooks and router functions:

- `useEffect` hook from `react`
- `useLocation` and `useNavigationType` hooks from `react-router`
- `createRoutesFromChildren` and `matchRoutes` functions from `react-router`

<Alert level="warning">

To ensure proper routing instrumentation, initialize Sentry by calling `Sentry.init` **before**:

- Wrapping your `<Routes />` component
- Using `useRoutes`
- Using `wrapCreateBrowserRouterV7` or `wrapCreateMemoryRouterV7`

<Alert level="info" title="Looking for framework mode?">
React Router v7 (framework mode) is currently in experimental Alpha, check out
the docs [here](/platforms/javascript/guides/react-router/).
</Alert>
Apply the following setup steps based on your routing method and create a
[custom error boundary](#set-up-a-custom-error-boundary) to make sure Sentry
automatically captures rendering errors:

### Usage with `createBrowserRouter` or `createMemoryRouter`

If you choose to create your router instance with [`createBrowserRouter`](https://reactrouter.com/en/main/routers/create-browser-router) or [`createMemoryRouter`](https://reactrouter.com/en/main/routers/create-memory-router), you can use `Sentry.wrapCreateBrowserRouterV7` or `Sentry.wrapCreateMemoryRouterV7` to wrap it with the instrumentation:

<Alert level="warning" title="Note">
<TableOfContents ignoreIds={["set-up-a-custom-error-boundary", "next-steps"]} />

`wrapCreateMemoryRouterV7` was introduced in SDK version 8.50.0. Prior to that version, we suggested using `wrapCreateBrowserRouterV7` with `createMemoryRouter`. If you are currently using `wrapCreateBrowserRouterV7` to wrap `createMemoryRouter`, it is recommended that you use `wrapCreateMemoryRouterV7` instead.
## Usage with `createBrowserRouter` or `createMemoryRouter`

You can instrument [`createHashRouter`](https://reactrouter.com/en/main/routers/create-hash-router) using the `wrapCreateBrowserRouterV7` function.
To instrument your React Router, update your `Sentry.browserTracingIntegration` to `Sentry.reactRouterV7BrowserTracingIntegration` within `Sentry.init` and provide the required React hooks and router functions. Then, wrap the router instance created by `createBrowserRouter` or `createMemoryRouter` with one of the following functions:

</Alert>
- Use `Sentry.wrapCreateBrowserRouterV7` for [`createBrowserRouter`](https://reactrouter.com/en/main/routers/create-browser-router) and [`createHashRouter`](https://reactrouter.com/en/main/routers/create-hash-router)
- Use `Sentry.wrapCreateMemoryRouterV7` for [`createMemoryRouter`](https://reactrouter.com/en/main/routers/create-memory-router) (introduced in SDK version `8.50.0`)

```javascript {2-8, 15-21, 26-33}
import React from "react";
Expand Down Expand Up @@ -76,9 +55,9 @@ const router = sentryCreateBrowserRouter([
]);
```

### Usage With `<Routes />` Component
## Usage With `<Routes />` Component

If you're using the `<Routes />` component to define your routes, wrap [`Routes`](https://reactrouter.com/en/main/components/routes) using `Sentry.withSentryReactRouterV7Routing`. This creates a higher order component, which will enable Sentry to reach your router context. You can also use `Sentry.withSentryReactRouterV7Routing` for `Routes` inside `BrowserRouter`. `MemoryRouter`, and `HashRouter` components:
If you're using the `<Routes />` component to define your routes, update your `Sentry.browserTracingIntegration` to `Sentry.reactRouterV7BrowserTracingIntegration` inside `Sentry.init` and provide the required React hooks and router functions. Then, wrap `<Routes />` using `Sentry.withSentryReactRouterV7Routing`. This creates a higher order component, which will enable Sentry to reach your router context. You can also use `Sentry.withSentryReactRouterV7Routing` for routes inside `BrowserRouter`, `MemoryRouter`, and `HashRouter` components.

```javascript {3-11, 18-24, 29, 33-35}
import React from "react";
Expand Down Expand Up @@ -120,15 +99,14 @@ ReactDOM.render(
);
```

This is only needed at the top level of your app, rather than how v4/v5 required wrapping every `<Route/>` you wanted parametrized.

### Usage With `useRoutes` Hook
This wrapper is only needed at the top level of your app, unlike React Router v4/v5, which required wrapping every `<Route />` you wanted parametrized.

If you specify your route definitions as an object to the [`useRoutes` hook](https://reactrouter.com/en/main/hooks/use-routes), use `Sentry.wrapUseRoutesV7` to create a patched `useRoutes` hook that instruments your routes with Sentry.
## Usage With `useRoutes` Hook

<Alert level="warning">
If you specify your route definitions as an object to the [`useRoutes` hook](https://reactrouter.com/en/main/hooks/use-routes), update your `Sentry.browserTracingIntegration` to `Sentry.reactRouterV7BrowserTracingIntegration` inside `Sentry.init` and provide the required React hooks and router functions. Then, use `Sentry.wrapUseRoutesV7` to create a patched `useRoutes` hook that instruments your routes with Sentry.

`wrapUseRoutesV7` should be called outside of a React component, as in the example below. It's also recommended that you assign the wrapped hook to a variable name starting with `use`, as per the [React documentation](https://reactjs.org/docs/hooks-custom.html#extracting-a-custom-hook).
<Alert level="warning" title="Important">
Call `wrapUseRoutesV7` outside of a React component, as in the example below. We also recommend that you assign the wrapped hook to a variable starting with `use`, as per [React's documentation](https://react.dev/learn/reusing-logic-with-custom-hooks#hook-names-always-start-with-use).

</Alert>

Expand Down Expand Up @@ -174,16 +152,13 @@ ReactDOM.render(
);
```

Now, Sentry should generate `pageload`/`navigation` transactions with parameterized transaction names (for example, `/teams/:teamid/user/:userid`), where applicable. This is only needed at the top level of your app, rather than how v4/v5 required wrapping every `<Route/>` you wanted parametrized.
Now, Sentry should generate `pageload`/`navigation` transactions with parameterized transaction names (for example, `/teams/:teamid/user/:userid`), where applicable. This is only needed at the top level of your app, unlike React Router v4/v5, which required wrapping every `<Route />` you wanted parametrized.

### Custom Error Boundaries
## Set Up a Custom Error Boundary

When using `react-router`, errors thrown inside route elements will only be re-thrown in **development mode** while using [`strict mode`](https://react.dev/reference/react/StrictMode). In production, these errors won't be surfaced unless manually captured. If you **don't** have a custom error boundary in place, `react-router` will create a default one that "swallows" all errors.

<Alert>
Note, that this only applies to render method and lifecycle errors since React
doesn't need error boundaries to handle errors in event handlers.
</Alert>
When using `react-router`, errors thrown inside route elements will only be re-thrown in **development mode** while using [`strict mode`](https://react.dev/reference/react/StrictMode).\
In production, these errors won't surface unless captured manually. If you **don't** have a custom error boundary in place, `react-router` will create a default one that "swallows" all errors.\
Hence, to capture these errors with Sentry in production, we strongly recommend to implement a custom error boundary.

To send errors to Sentry while using a custom error boundary, use the `Sentry.captureException` method:

Expand Down Expand Up @@ -227,7 +202,7 @@ export function YourCustomRootErrorBoundary() {

```

## Next Steps:
## Next Steps

- [Return to **Getting Started**](../../)
- [Return to the main integrations page](../)