Skip to content

Commit ae086f9

Browse files
authored
feat(remix): Wrap root with ErrorBoundary. (#5365)
Wraps the Remix root with `ErrorBoundary` while wrapping it with the router instrumentation.
1 parent 3e7a3ec commit ae086f9

File tree

5 files changed

+58
-21
lines changed

5 files changed

+58
-21
lines changed

packages/react/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export * from '@sentry/browser';
22

33
export { init } from './sdk';
44
export { Profiler, withProfiler, useProfiler } from './profiler';
5-
export type { FallbackRender } from './errorboundary';
5+
export type { ErrorBoundaryProps, FallbackRender } from './errorboundary';
66
export { ErrorBoundary, withErrorBoundary } from './errorboundary';
77
export { createReduxEnhancer } from './redux';
88
export { reactRouterV3Instrumentation } from './reactrouterv3';

packages/remix/README.md

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ Sentry.init({
5757
});
5858
```
5959

60-
Also, wrap your Remix root, with Sentry's `ErrorBoundary` component to catch React component errors, and `withSentryRouteTracing` to get parameterized router transactions.
60+
Also, wrap your Remix root with `withSentry` to catch React component errors and to get parameterized router transactions.
6161

6262
```ts
6363
// root.tsx
@@ -71,28 +71,43 @@ import {
7171
ScrollRestoration,
7272
} from "@remix-run/react";
7373

74-
import { ErrorBoundary, withSentryRouteTracing } from "@sentry/remix";
74+
import { withSentry } from "@sentry/remix";
7575

7676
function App() {
7777
return (
78-
<ErrorBoundary>
79-
<html>
80-
<head>
81-
<Meta />
82-
<Links />
83-
</head>
84-
<body>
85-
<Outlet />
86-
<ScrollRestoration />
87-
<Scripts />
88-
<LiveReload />
89-
</body>
90-
</html>
91-
</ErrorBoundary>
78+
<html>
79+
<head>
80+
<Meta />
81+
<Links />
82+
</head>
83+
<body>
84+
<Outlet />
85+
<ScrollRestoration />
86+
<Scripts />
87+
<LiveReload />
88+
</body>
89+
</html>
9290
);
9391
}
9492

95-
export default withSentryRouteTracing(App);
93+
export default withSentry(App);
94+
```
95+
96+
You can disable or configure `ErrorBoundary` using a second parameter to `withSentry`.
97+
98+
```ts
99+
100+
withSentry(App, {
101+
wrapWithErrorBoundary: false
102+
});
103+
104+
// or
105+
106+
withSentry(App, {
107+
errorBoundaryOptions: {
108+
fallback: <p>An error has occurred</p>
109+
}
110+
});
96111
```
97112

98113
To set context information or send manual events, use the exported functions of `@sentry/remix`.

packages/remix/src/index.client.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { configureScope, init as reactInit, Integrations } from '@sentry/react';
33

44
import { buildMetadata } from './utils/metadata';
55
import { RemixOptions } from './utils/remixOptions';
6-
export { remixRouterInstrumentation, withSentryRouteTracing } from './performance/client';
6+
export { remixRouterInstrumentation, withSentry } from './performance/client';
77
export { BrowserTracing } from '@sentry/tracing';
88
export * from '@sentry/react';
99

packages/remix/src/index.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { buildMetadata } from './utils/metadata';
77
import { RemixOptions } from './utils/remixOptions';
88

99
export { ErrorBoundary, withErrorBoundary } from '@sentry/react';
10-
export { remixRouterInstrumentation, withSentryRouteTracing } from './performance/client';
10+
export { remixRouterInstrumentation, withSentry } from './performance/client';
1111
export { BrowserTracing, Integrations } from '@sentry/tracing';
1212
export * from '@sentry/node';
1313

packages/remix/src/performance/client.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { ErrorBoundaryProps } from '@sentry/react';
2+
import { withErrorBoundary } from '@sentry/react';
13
import { Transaction, TransactionContext } from '@sentry/types';
24
import { getGlobalObject, logger } from '@sentry/utils';
35
import * as React from 'react';
@@ -79,8 +81,21 @@ export function remixRouterInstrumentation(useEffect: UseEffect, useLocation: Us
7981
/**
8082
* Wraps a remix `root` (see: https://remix.run/docs/en/v1/guides/migrating-react-router-app#creating-the-root-route)
8183
* To enable pageload/navigation tracing on every route.
84+
* Also wraps the application with `ErrorBoundary`.
85+
*
86+
* @param OrigApp The Remix root to wrap
87+
* @param options The options for ErrorBoundary wrapper.
8288
*/
83-
export function withSentryRouteTracing<P extends Record<string, unknown>, R extends React.FC<P>>(OrigApp: R): R {
89+
export function withSentry<P extends Record<string, unknown>, R extends React.FC<P>>(
90+
OrigApp: R,
91+
options: {
92+
wrapWithErrorBoundary?: boolean;
93+
errorBoundaryOptions?: ErrorBoundaryProps;
94+
} = {
95+
wrapWithErrorBoundary: true,
96+
errorBoundaryOptions: {},
97+
},
98+
): R {
8499
const SentryRoot: React.FC<P> = (props: P) => {
85100
// Early return when any of the required functions is not available.
86101
if (!_useEffect || !_useLocation || !_useMatches || !_customStartTransaction) {
@@ -91,6 +106,7 @@ export function withSentryRouteTracing<P extends Record<string, unknown>, R exte
91106
// will break advanced type inference done by react router params
92107
return <OrigApp {...props} />;
93108
}
109+
94110
let isBaseLocation: boolean = false;
95111

96112
const location = _useLocation();
@@ -133,6 +149,12 @@ export function withSentryRouteTracing<P extends Record<string, unknown>, R exte
133149
return <OrigApp {...props} />;
134150
};
135151

152+
if (options.wrapWithErrorBoundary) {
153+
// @ts-ignore Setting more specific React Component typing for `R` generic above
154+
// will break advanced type inference done by react router params
155+
return withErrorBoundary(SentryRoot, options.errorBoundaryOptions);
156+
}
157+
136158
// @ts-ignore Setting more specific React Component typing for `R` generic above
137159
// will break advanced type inference done by react router params
138160
return SentryRoot;

0 commit comments

Comments
 (0)