From 9feb09402975f5dfb81e1c5e634e2c22d929c693 Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Mon, 2 Dec 2024 15:47:41 +0100 Subject: [PATCH] docs(react): Add React Router v7 docs (#11990) --- .../guides/react/features/react-router.mdx | 372 ------------------ .../react/features/react-router/index.mdx | 22 ++ .../guides/react/features/react-router/v3.mdx | 45 +++ .../react/features/react-router/v4-5.mdx | 101 +++++ .../guides/react/features/react-router/v6.mdx | 234 +++++++++++ .../guides/react/features/react-router/v7.mdx | 227 +++++++++++ 6 files changed, 629 insertions(+), 372 deletions(-) delete mode 100644 docs/platforms/javascript/guides/react/features/react-router.mdx create mode 100644 docs/platforms/javascript/guides/react/features/react-router/index.mdx create mode 100644 docs/platforms/javascript/guides/react/features/react-router/v3.mdx create mode 100644 docs/platforms/javascript/guides/react/features/react-router/v4-5.mdx create mode 100644 docs/platforms/javascript/guides/react/features/react-router/v6.mdx create mode 100644 docs/platforms/javascript/guides/react/features/react-router/v7.mdx diff --git a/docs/platforms/javascript/guides/react/features/react-router.mdx b/docs/platforms/javascript/guides/react/features/react-router.mdx deleted file mode 100644 index a856e1b45bcb47..00000000000000 --- a/docs/platforms/javascript/guides/react/features/react-router.mdx +++ /dev/null @@ -1,372 +0,0 @@ ---- -title: React Router -description: "Learn about Sentry's React Router integration." ---- - -_(Available in version 5.21.0 and above)_ - -React Router support is included in the `@sentry/react` package since version `5.21.0`. - - - -The React Router integration is designed to work with Sentry Tracing. Please see [Set Up Tracing with React](/platforms/javascript/guides/react/tracing/) for more details on how to set up and install the SDK. - - - -The React Router instrumentation uses the React Router library to create `pageload/navigation` transactions to ensure you collect meaningful performance data about the health of your page loads and associated requests. - -We support integrations for React Router 3, 4, 5, and 6. - -## React Router v6 - -_(Available in version 7 and above)_ - -To use React Router v6 with Sentry: - -Add `Sentry.reactRouterV6BrowserTracingIntegration` instead of the regular `Sentry.browserTracingIntegration` and provide the required React hooks and router functions: - - - `useEffect` hook from `react` - - `useLocation` and `useNavigationType` hooks from `react-router-dom` - - `createRoutesFromChildren` and `matchRoutes` functions from `react-router-dom` or `react-router` packages, depending on which package you're using. - - - -Make sure you call `Sentry.init`, **before** you wrap your `` component or the `useRoutes` hook. Otherwise, the routing instrumentation may not work properly. - - - -### Usage with React Router 6.4 Data API - -_(Available in version 7.21.0 and above)_ - -If you choose to create your router instance with [`createBrowserRouter`](https://reactrouter.com/en/main/routers/create-browser-router) from the `react-router-dom` package, you can use `Sentry.wrapCreateBrowserRouter` to wrap it with the instrumentation: - - -```javascript {2-8, 15-21, 26-33} -import React from "react"; -import { - createBrowserRouter, - createRoutesFromChildren, - matchRoutes, - useLocation, - useNavigationType, -} from "react-router-dom"; - -import * as Sentry from "@sentry/react"; - -Sentry.init({ - dsn: "___PUBLIC_DSN___", - integrations: [ - Sentry.reactRouterV6BrowserTracingIntegration({ - useEffect: React.useEffect, - useLocation, - useNavigationType, - createRoutesFromChildren, - matchRoutes, - }), - ], - tracesSampleRate: 1.0, -}); - -const sentryCreateBrowserRouter = - Sentry.wrapCreateBrowserRouter(createBrowserRouter); - -const router = sentryCreateBrowserRouter([ - // your routes... -]); -``` - - - -You can instrument [`createMemoryRouter`](https://reactrouter.com/en/main/routers/create-memory-router) and [`createHashRouter`](https://reactrouter.com/en/main/routers/create-hash-router) using the `wrapCreateBrowserRouter` function. - - - -### Custom Error Boundaries - -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. - - -Note, that this only applies to render method and lifecycle errors since React doesn't need error boundaries to handle errors in event handlers. - - -To send errors to Sentry while using a custom error boundary, use the `Sentry.captureException` method: - -```jsx {11, 28} -// router setup -const sentryCreateBrowserRouter = wrapCreateBrowserRouter(createBrowserRouter); -const router = sentryCreateBrowserRouter([ - { - path: "/", - element: , - children: [ - { - path: "", - element: , - errorElement: , - children: [ - // other routes ... - ], - }, - ], - }, -]); - -// error boundary -import { useRouteError } from "react-router-dom"; -import * as Sentry from "@sentry/react"; - -export function YourCustomRootErrorBoundary() { - const error = useRouteError() as Error; - - React.useEffect(() => { - Sentry.captureException(error); - }, [error]); - - return ( -
-

Ouch!

-
- ); -} - -``` - - -### Usage With `` Component - -If you're using the `` component from `react-router-dom` 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: - - -```javascript {3-11, 18-24, 29, 33-35} -import React from "react"; -import ReactDOM from "react-dom"; -import { - Routes, - Route, - BrowserRouter, - useLocation, - useNavigationType, - createRoutesFromChildren, - matchRoutes, -} from "react-router-dom"; - -import * as Sentry from "@sentry/react"; - -Sentry.init({ - dsn: "___PUBLIC_DSN___", - integrations: [ - Sentry.reactRouterV6BrowserTracingIntegration({ - useEffect: React.useEffect, - useLocation, - useNavigationType, - createRoutesFromChildren, - matchRoutes, - }), - ], - tracesSampleRate: 1.0, -}); - -const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes); - -ReactDOM.render( - - - Home} /> - - -); -``` - -This is only needed at the top level of your app, rather than how v4/v5 required wrapping every `` you wanted parametrized. - -### Usage With `useRoutes` Hook - -_(Available in 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.wrapUseRoutes` to create a patched `useRoutes` hook that instruments your routes with Sentry. - - - -`wrapUseRoutes` 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). - - - - -```javascript {2-10, 15-21, 26, 29-31} -import React from "react"; -import { - createRoutesFromChildren, - matchRoutes, - useLocation, - useNavigationType, - useRoutes, -} from "react-router-dom"; - -import { wrapUseRoutes } from "@sentry/react"; - -Sentry.init({ - dsn: "___PUBLIC_DSN___", - integrations: [ - Sentry.reactRouterV6BrowserTracingIntegration({ - useEffect: React.useEffect, - useLocation, - useNavigationType, - createRoutesFromChildren, - matchRoutes, - }), - ], - tracesSampleRate: 1.0, -}); - -const useSentryRoutes = wrapUseRoutes(useRoutes); - -function App() { - return useSentryRoutes([ - // your routes... - ]); -} - -ReactDOM.render( - - - , - document.getElementById("root") -); -``` - -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 `` you wanted parametrized. - -## React Router v4/v5 - -Make sure you use a `Router` component combined with `createBrowserHistory` (or equivalent). - -### Parameterized Transaction Names - -To get parameterized transaction names (for example, `/teams/:teamid/user/:userid` instead of `/teams/123/user/345`), you must explicitly set the routes you want parameterized. That's because there is no static route config that the SDK can use in React Router v4/v5. - -We recommend you use the `withSentryRouting` higher order component to create a `SentryRoute` component that will update the match path on render. - - -```javascript {1, 7, 14-16, 28-30} -import {Route, Router, Switch } from 'react-router-dom'; -import { createBrowserHistory } from 'history'; - -import * as Sentry from '@sentry/react'; - -// Create Custom Sentry Route component -const SentryRoute = Sentry.withSentryRouting(Route); - -const history = createBrowserHistory(); - -Sentry.init({ - dsn: "___PUBLIC_DSN___", - integrations: [ - Sentry.reactRouterV5BrowserTracingIntegration({ history }), - // OR - Sentry.reactRouterV4BrowserTracingIntegration({ history }), - ], - - // We recommend adjusting this value in production, or using tracesSampler - // for finer control - tracesSampleRate: 1.0, -}); - -render() { - return ( - - -
UserId
} /> -
Users
} /> -
Home
} /> -
-
- ); -} -``` - -If you don't want to wrap individual routes, you can still specify parameterized routes manually by passing an array of route config objects, per [react-router-config](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-config), to the instrumentation function call. You'll also need to provide the `matchPath` function exported from the `react-router-dom` or `react-router` packages. - - -```javascript {1,8-10,15-19} -import { Route, Router, Switch, matchPath } from 'react-router-dom'; -import { createBrowserHistory } from 'history'; - -import * as Sentry from '@sentry/react'; - -const history = createBrowserHistory(); - -// Array of Route Config Objects -// Make sure the order of the routes is correct. The longest url under the same parent should be placed first and in decreasing order. -const routes = [{ path: '/users/:userid' }, { path: '/users' }, { path: '/' }]; - -Sentry.init({ - dsn: "___PUBLIC_DSN___", - integrations: [ - Sentry.reactRouterV5BrowserTracingIntegration({ - history, - routes, - matchPath - }), - ], - - // We recommend adjusting this value in production, or using tracesSampler - // for finer control - tracesSampleRate: 1.0, -}); - -// In your App render: -render() { - return ( - - -
UserId
} /> -
Users
} /> -
Home
} /> -
-
- ); -} -``` - -## React Router v3 - -To use the router integration, import and set a custom routing instrumentation and pass it the history, your routes and a match function. React Router v3 support is maintained for React Router >= 3.2.0 and < 4.0.0. - - -```javascript {18-23} -import * as Router from "react-router"; - -import * as Sentry from "@sentry/react"; - -// Routes looks like this: -const routes = ( - - -
OrgId
} /> -
Team
} /> -
-
-); - -Sentry.init({ - dsn: "___PUBLIC_DSN___", - integrations: [ - Sentry.reactRouterV3BrowserTracingIntegration({ - history: Router.browserHistory, - // Must be Plain Routes. - routes: Router.createRoutes(routes), - match: Router.match, - }), - ], - - // We recommend adjusting this value in production, or using tracesSampler - // for finer control - tracesSampleRate: 1.0, -}); -``` - -## Next Steps: - -- [Return to **Getting Started**](../../) -- [Return to the main integrations page](../) diff --git a/docs/platforms/javascript/guides/react/features/react-router/index.mdx b/docs/platforms/javascript/guides/react/features/react-router/index.mdx new file mode 100644 index 00000000000000..3a0c20cb7b2a53 --- /dev/null +++ b/docs/platforms/javascript/guides/react/features/react-router/index.mdx @@ -0,0 +1,22 @@ +--- +title: React Router +description: "Learn about Sentry's React Router integration." +--- + +_(Available in version 5.21.0 and above)_ + +React Router support is included in the `@sentry/react` package since version `5.21.0`. + + + +The React Router integration is designed to work with Sentry Tracing. Please see [Set Up Tracing with React](/platforms/javascript/guides/react/tracing/) for more details on how to set up and install the SDK. + + + +The React Router instrumentation uses the React Router library to create `pageload/navigation` transactions to ensure you collect meaningful performance data about the health of your page loads and associated requests. + +We support integrations for React Router 3, 4, 5, 6 and 7. + + + + \ No newline at end of file diff --git a/docs/platforms/javascript/guides/react/features/react-router/v3.mdx b/docs/platforms/javascript/guides/react/features/react-router/v3.mdx new file mode 100644 index 00000000000000..fabfc5c2ecfefe --- /dev/null +++ b/docs/platforms/javascript/guides/react/features/react-router/v3.mdx @@ -0,0 +1,45 @@ +--- +title: React Router v3 +description: "Learn about Sentry's React Router v3 integration." +sidebar_order: 40 +--- + +To use the router integration, import and set a custom routing instrumentation and pass it the history, your routes and a match function. React Router v3 support is maintained for React Router >= 3.2.0 and < 4.0.0. + + +```javascript {18-23} +import * as Router from "react-router"; + +import * as Sentry from "@sentry/react"; + +// Routes looks like this: +const routes = ( + + +
OrgId
} /> +
Team
} /> +
+
+); + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [ + Sentry.reactRouterV3BrowserTracingIntegration({ + history: Router.browserHistory, + // Must be Plain Routes. + routes: Router.createRoutes(routes), + match: Router.match, + }), + ], + + // We recommend adjusting this value in production, or using tracesSampler + // for finer control + tracesSampleRate: 1.0, +}); +``` + +## Next Steps: + +- [Return to **Getting Started**](../../) +- [Return to the main integrations page](../) \ No newline at end of file diff --git a/docs/platforms/javascript/guides/react/features/react-router/v4-5.mdx b/docs/platforms/javascript/guides/react/features/react-router/v4-5.mdx new file mode 100644 index 00000000000000..e2f362c957f25d --- /dev/null +++ b/docs/platforms/javascript/guides/react/features/react-router/v4-5.mdx @@ -0,0 +1,101 @@ +--- +title: React Router v4 and v5 +description: "Learn about Sentry's React Router v4 / v5 integration." +sidebar_order: 30 +--- + + +Make sure you use a `Router` component combined with `createBrowserHistory` (or equivalent). + +### Parameterized Transaction Names + +To get parameterized transaction names (for example, `/teams/:teamid/user/:userid` instead of `/teams/123/user/345`), you must explicitly set the routes you want parameterized. That's because there is no static route config that the SDK can use in React Router v4/v5. + +We recommend you use the `withSentryRouting` higher order component to create a `SentryRoute` component that will update the match path on render. + + +```javascript {1, 7, 14-16, 28-30} +import {Route, Router, Switch } from 'react-router-dom'; +import { createBrowserHistory } from 'history'; + +import * as Sentry from '@sentry/react'; + +// Create Custom Sentry Route component +const SentryRoute = Sentry.withSentryRouting(Route); + +const history = createBrowserHistory(); + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [ + Sentry.reactRouterV5BrowserTracingIntegration({ history }), + // OR + Sentry.reactRouterV4BrowserTracingIntegration({ history }), + ], + + // We recommend adjusting this value in production, or using tracesSampler + // for finer control + tracesSampleRate: 1.0, +}); + +render() { + return ( + + +
UserId
} /> +
Users
} /> +
Home
} /> +
+
+ ); +} +``` + +If you don't want to wrap individual routes, you can still specify parameterized routes manually by passing an array of route config objects, per [react-router-config](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-config), to the instrumentation function call. You'll also need to provide the `matchPath` function exported from the `react-router-dom` or `react-router` packages. + + +```javascript {1,8-10,15-19} +import { Route, Router, Switch, matchPath } from 'react-router-dom'; +import { createBrowserHistory } from 'history'; + +import * as Sentry from '@sentry/react'; + +const history = createBrowserHistory(); + +// Array of Route Config Objects +// Make sure the order of the routes is correct. The longest url under the same parent should be placed first and in decreasing order. +const routes = [{ path: '/users/:userid' }, { path: '/users' }, { path: '/' }]; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [ + Sentry.reactRouterV5BrowserTracingIntegration({ + history, + routes, + matchPath + }), + ], + + // We recommend adjusting this value in production, or using tracesSampler + // for finer control + tracesSampleRate: 1.0, +}); + +// In your App render: +render() { + return ( + + +
UserId
} /> +
Users
} /> +
Home
} /> +
+
+ ); +} +``` + +## Next Steps: + +- [Return to **Getting Started**](../../) +- [Return to the main integrations page](../) \ No newline at end of file diff --git a/docs/platforms/javascript/guides/react/features/react-router/v6.mdx b/docs/platforms/javascript/guides/react/features/react-router/v6.mdx new file mode 100644 index 00000000000000..dd7d8ad33507dc --- /dev/null +++ b/docs/platforms/javascript/guides/react/features/react-router/v6.mdx @@ -0,0 +1,234 @@ +--- +title: React Router v6 +description: "Learn about Sentry's React Router v6 integration." +sidebar_order: 20 +--- + + +- React Router v6 support is included in the `@sentry/react` package since version `7`. + + +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` + + + +Make sure you call `Sentry.init`, **before** you wrap your `` component or the `useRoutes` hook. Otherwise, the routing instrumentation may not work properly. + + + +### Usage with `createBrowserRouter` + + +Available in `@sentry/react` version `7.21.0` and above. + + +If you choose to create your router instance with [`createBrowserRouter`](https://reactrouter.com/en/main/routers/create-browser-router) from the `react-router-dom` package, you can use `Sentry.wrapCreateBrowserRouterV6` to wrap it with the instrumentation: + + +```javascript {2-8, 15-21, 26-33} +import React from "react"; +import { + createBrowserRouter, + createRoutesFromChildren, + matchRoutes, + useLocation, + useNavigationType, +} from "react-router-dom"; + +import * as Sentry from "@sentry/react"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [ + Sentry.reactRouterV6BrowserTracingIntegration({ + useEffect: React.useEffect, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes, + }), + ], + tracesSampleRate: 1.0, +}); + +const sentryCreateBrowserRouter = + Sentry.wrapCreateBrowserRouter(createBrowserRouter); + +const router = sentryCreateBrowserRouter([ + // your routes... +]); +``` + + + +You can instrument [`createMemoryRouter`](https://reactrouter.com/en/main/routers/create-memory-router) and [`createHashRouter`](https://reactrouter.com/en/main/routers/create-hash-router) using the `wrapCreateBrowserRouter` function. + + + + +### Usage With `` Component + +If you're using the `` 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: + + +```javascript {3-11, 18-24, 29, 33-35} +import React from "react"; +import ReactDOM from "react-dom"; +import { + Routes, + Route, + BrowserRouter, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes, +} from "react-router-dom"; + +import * as Sentry from "@sentry/react"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [ + Sentry.reactRouterV6BrowserTracingIntegration({ + useEffect: React.useEffect, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes, + }), + ], + tracesSampleRate: 1.0, +}); + +const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes); + +ReactDOM.render( + + + Home} /> + + +); +``` + +This is only needed at the top level of your app, rather than how v4/v5 required wrapping every `` you wanted parametrized. + +### Usage With `useRoutes` Hook + + +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. + + + +`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). + + + + +```javascript {2-10, 15-21, 26, 29-31} +import React from "react"; +import { + createRoutesFromChildren, + matchRoutes, + useLocation, + useNavigationType, + useRoutes, +} from "react-router-dom"; + +import { wrapUseRoutes } from "@sentry/react"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [ + Sentry.reactRouterV6BrowserTracingIntegration({ + useEffect: React.useEffect, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes, + }), + ], + tracesSampleRate: 1.0, +}); + +const useSentryRoutes = wrapUseRoutesV6(useRoutes); + +function App() { + return useSentryRoutes([ + // your routes... + ]); +} + +ReactDOM.render( + + + , + document.getElementById("root") +); +``` + +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 `` you wanted parametrized. + + +### Custom Error Boundaries + +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. + + +Note, that this only applies to render method and lifecycle errors since React doesn't need error boundaries to handle errors in event handlers. + + +To send errors to Sentry while using a custom error boundary, use the `Sentry.captureException` method: + +```jsx {11, 28} +// router setup +const sentryCreateBrowserRouter = wrapCreateBrowserRouterV6(createBrowserRouter); +const router = sentryCreateBrowserRouter([ + { + path: "/", + element: , + children: [ + { + path: "", + element: , + errorElement: , + children: [ + // other routes ... + ], + }, + ], + }, +]); + +// error boundary +import { useRouteError } from "react-router-dom"; +import * as Sentry from "@sentry/react"; + +export function YourCustomRootErrorBoundary() { + const error = useRouteError() as Error; + + React.useEffect(() => { + Sentry.captureException(error); + }, [error]); + + return ( +
+

Ouch!

+
+ ); +} + +``` + + +## Next Steps: + +- [Return to **Getting Started**](../../) +- [Return to the main integrations page](../) \ No newline at end of file diff --git a/docs/platforms/javascript/guides/react/features/react-router/v7.mdx b/docs/platforms/javascript/guides/react/features/react-router/v7.mdx new file mode 100644 index 00000000000000..4fb5e03929e4de --- /dev/null +++ b/docs/platforms/javascript/guides/react/features/react-router/v7.mdx @@ -0,0 +1,227 @@ +--- +title: React Router v7 +description: "Learn about Sentry's React Router v7 integration." +sidebar_order: 10 +--- + + +- React Router v7 (library mode) support is included in the `@sentry/react` package since version `8.42.0`. +- React Router v7 (framework mode) is not yet supported. + + +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` + + + +Make sure you call `Sentry.init`, **before** you wrap your `` component or the `useRoutes` hook. Otherwise, the routing instrumentation may not work properly. + + + +### Usage with `createBrowserRouter` + +If you choose to create your router instance with [`createBrowserRouter`](https://reactrouter.com/en/main/routers/create-browser-router) from the `react-router` package, you can use `Sentry.wrapCreateBrowserRouterV7` to wrap it with the instrumentation: + + +```javascript {2-8, 15-21, 26-33} +import React from "react"; +import { + createBrowserRouter, + createRoutesFromChildren, + matchRoutes, + useLocation, + useNavigationType, +} from "react-router"; + +import * as Sentry from "@sentry/react"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [ + Sentry.reactRouterV7BrowserTracingIntegration({ + useEffect: React.useEffect, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes, + }), + ], + tracesSampleRate: 1.0, +}); + +const sentryCreateBrowserRouter = + Sentry.wrapCreateBrowserRouterV7(createBrowserRouter); + +const router = sentryCreateBrowserRouter([ + // your routes... +]); +``` + + + +You can instrument [`createMemoryRouter`](https://reactrouter.com/en/main/routers/create-memory-router) and [`createHashRouter`](https://reactrouter.com/en/main/routers/create-hash-router) using the `wrapCreateBrowserRouter` function. + + + + +### Usage With `` Component + +If you're using the `` 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: + + +```javascript {3-11, 18-24, 29, 33-35} +import React from "react"; +import ReactDOM from "react-dom"; +import { + Routes, + Route, + BrowserRouter, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes, +} from "react-router"; + +import * as Sentry from "@sentry/react"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [ + Sentry.reactRouterV7BrowserTracingIntegration({ + useEffect: React.useEffect, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes, + }), + ], + tracesSampleRate: 1.0, +}); + +const SentryRoutes = Sentry.withSentryReactRouterV7Routing(Routes); + +ReactDOM.render( + + + Home} /> + + +); +``` + +This is only needed at the top level of your app, rather than how v4/v5 required wrapping every `` you wanted parametrized. + +### Usage With `useRoutes` Hook + +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. + + + +`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). + + + + +```javascript {2-10, 15-21, 26, 29-31} +import React from "react"; +import { + createRoutesFromChildren, + matchRoutes, + useLocation, + useNavigationType, + useRoutes, +} from "react-router"; + +import { wrapUseRoutes } from "@sentry/react"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + integrations: [ + Sentry.reactRouterV7BrowserTracingIntegration({ + useEffect: React.useEffect, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes, + }), + ], + tracesSampleRate: 1.0, +}); + +const useSentryRoutes = wrapUseRoutesV7(useRoutes); + +function App() { + return useSentryRoutes([ + // your routes... + ]); +} + +ReactDOM.render( + + + , + document.getElementById("root") +); +``` + +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 `` you wanted parametrized. + + +### Custom Error Boundaries + +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. + + +Note, that this only applies to render method and lifecycle errors since React doesn't need error boundaries to handle errors in event handlers. + + +To send errors to Sentry while using a custom error boundary, use the `Sentry.captureException` method: + + +```jsx {11, 28} +// router setup +const sentryCreateBrowserRouter = wrapCreateBrowserRouterV7(createBrowserRouter); +const router = sentryCreateBrowserRouter([ + { + path: "/", + element: , + children: [ + { + path: "", + element: , + errorElement: , + children: [ + // other routes ... + ], + }, + ], + }, +]); + +// error boundary +import { useRouteError } from "react-router-dom"; +import * as Sentry from "@sentry/react"; + +export function YourCustomRootErrorBoundary() { + const error = useRouteError() as Error; + + React.useEffect(() => { + Sentry.captureException(error); + }, [error]); + + return ( +
+

Ouch!

+
+ ); +} + +``` + +## Next Steps: + +- [Return to **Getting Started**](../../) +- [Return to the main integrations page](../) \ No newline at end of file