React Router v7
了解 Sentry 的 React Router v7 集成。
- React Router v7(库模式)支持自版本
8.42.0
起包含在@sentry/react
包中。 - React Router v7(框架模式)尚不支持。
将你的 Sentry.browserTracingIntegration
更新为 Sentry.reactRouterV7BrowserTracingIntegration
,并提供所需的 React 钩子和路由器函数:
- 来自
react
的useEffect
钩子 - 来自
react-router
的useLocation
和useNavigationType
钩子 - 来自
react-router
的createRoutesFromChildren
和matchRoutes
函数
为了确保正确的路由仪器化,在以下操作之前通过调用 Sentry.init
初始化 Sentry:
- 包装你的
<Routes />
组件 - 使用
useRoutes
- 使用
createBrowserRouterV7
如果你选择使用 react-router
包中的 createBrowserRouter
创建路由器实例,可以使用 Sentry.wrapCreateBrowserRouterV7
将其包装以进行仪器化:
import React from "react";
import {
createBrowserRouter,
createRoutesFromChildren,
matchRoutes,
useLocation,
useNavigationType,
} from "react-router";
import * as Sentry from "@sentry/react";
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
integrations: [
Sentry.reactRouterV7BrowserTracingIntegration({
useEffect: React.useEffect,
useLocation,
useNavigationType,
createRoutesFromChildren,
matchRoutes,
}),
],
tracesSampleRate: 1.0,
});
const sentryCreateBrowserRouter = Sentry.wrapCreateBrowserRouterV7(
createBrowserRouter,
);
const router = sentryCreateBrowserRouter([
// your routes...
]);
注意
你可以使用 wrapCreateBrowserRouter
函数来仪器化 createMemoryRouter
和 createHashRouter
。
如果你使用 <Routes />
组件定义路由,使用 Sentry.withSentryReactRouterV7Routing
包装 Routes
。这将创建一个高阶组件,使 Sentry 能够访问你的路由器上下文。你也可以在 BrowserRouter
、MemoryRouter
和 HashRouter
组件内部使用 Sentry.withSentryReactRouterV7Routing
来包装 Routes
:
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: "https://examplePublicKey@o0.ingest.sentry.io/0",
integrations: [
Sentry.reactRouterV7BrowserTracingIntegration({
useEffect: React.useEffect,
useLocation,
useNavigationType,
createRoutesFromChildren,
matchRoutes,
}),
],
tracesSampleRate: 1.0,
});
const SentryRoutes = Sentry.withSentryReactRouterV7Routing(Routes);
ReactDOM.render(
<BrowserRouter>
<SentryRoutes>
<Route path="/" element={<div>Home</div>} />
</SentryRoutes>
</BrowserRouter>,
);
这仅在应用的顶层需要,而不是像 v4/v5 那样需要包装每个你想要参数化的 <Route/>
。
如果你将路由定义作为对象传递给 useRoutes
钩子,使用 Sentry.wrapUseRoutesV7
创建一个修补过的 useRoutes
钩子,以便用 Sentry 仪器化你的路由。
wrapUseRoutesV7
应该在 React 组件外部调用,如下例所示。还建议将包装后的钩子赋值给以 use
开头的变量名,符合 React 文档 的要求。
import React from "react";
import {
createRoutesFromChildren,
matchRoutes,
useLocation,
useNavigationType,
useRoutes,
} from "react-router";
import { wrapUseRoutes } from "@sentry/react";
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
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(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById("root"),
);
现在,Sentry 应该生成带有参数化事务名称的 pageload
/navigation
事务(例如,/teams/:teamid/user/:userid
),在适用的情况下。这仅在应用的顶层需要,而不是像 v4/v5 那样需要包装每个你想要参数化的 <Route/>
。
当使用 react-router
时,在路由元素内部抛出的错误只会于 开发模式 下使用 strict mode
时重新抛出。在生产环境中,这些错误不会被暴露,除非手动捕获。如果你没有设置自定义错误边界,react-router
将创建一个默认的错误边界,该边界会“吞噬”所有错误。
注意,这仅适用于渲染方法和生命周期错误,因为 React 不需要错误边界来处理事件处理程序中的错误。
要在使用自定义错误边界时将错误发送到 Sentry,请使用 Sentry.captureException
方法:
// router setup
const sentryCreateBrowserRouter = wrapCreateBrowserRouterV7(createBrowserRouter);
const router = sentryCreateBrowserRouter([
{
path: "/",
element: <YourLayout />,
children: [
{
path: "",
element: <Outlet />,
errorElement: <YourCustomRootErrorBoundary />,
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 (
<div>
<h1>Ouch!</h1>
</div>
);
}