Skip to content

Commit 1142270

Browse files
committed
ref(react): Rely on error.cause to link ErrorBoundary errors
1 parent 27f8609 commit 1142270

File tree

2 files changed

+68
-35
lines changed

2 files changed

+68
-35
lines changed

packages/react/src/errorboundary.tsx

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
1-
import {
2-
captureEvent,
3-
captureException,
4-
eventFromException,
5-
ReportDialogOptions,
6-
Scope,
7-
showReportDialog,
8-
withScope,
9-
} from '@sentry/browser';
10-
import { Event } from '@sentry/types';
1+
import { captureException, ReportDialogOptions, Scope, showReportDialog, withScope } from '@sentry/browser';
112
import { logger, parseSemver } from '@sentry/utils';
123
import hoistNonReactStatics from 'hoist-non-react-statics';
134
import * as React from 'react';
@@ -71,31 +62,14 @@ const INITIAL_STATE = {
7162
* @param error An error captured by React Error Boundary
7263
* @param componentStack The component stacktrace
7364
*/
74-
function captureReactErrorBoundaryError(error: Error, componentStack: string): string {
75-
const errorBoundaryError = new Error(error.message);
76-
errorBoundaryError.name = `React ErrorBoundary ${errorBoundaryError.name}`;
77-
errorBoundaryError.stack = componentStack;
78-
79-
let errorBoundaryEvent: Event = {};
80-
void eventFromException({}, errorBoundaryError).then(e => {
81-
errorBoundaryEvent = e;
82-
});
83-
84-
if (
85-
errorBoundaryEvent.exception &&
86-
Array.isArray(errorBoundaryEvent.exception.values) &&
87-
reactVersion.major &&
88-
reactVersion.major >= 17
89-
) {
90-
let originalEvent: Event = {};
91-
void eventFromException({}, error).then(e => {
92-
originalEvent = e;
93-
});
94-
if (originalEvent.exception && Array.isArray(originalEvent.exception.values)) {
95-
originalEvent.exception.values = [...errorBoundaryEvent.exception.values, ...originalEvent.exception.values];
96-
}
97-
98-
return captureEvent(originalEvent);
65+
function captureReactErrorBoundaryError(error: Error & { cause?: Error }, componentStack: string): string {
66+
if (reactVersion.major && reactVersion.major >= 17) {
67+
const errorBoundaryError = new Error(error.message);
68+
errorBoundaryError.name = `React ErrorBoundary ${errorBoundaryError.name}`;
69+
errorBoundaryError.stack = componentStack;
70+
71+
error.cause = errorBoundaryError;
72+
return captureException(error);
9973
}
10074

10175
return captureException(error, { contexts: { react: { componentStack } } });
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { fireEvent, render, screen } from '@testing-library/react';
2+
import * as React from 'react';
3+
import { useState } from 'react';
4+
5+
import { init } from '../src';
6+
import { ErrorBoundary, ErrorBoundaryProps } from '../src/errorboundary';
7+
8+
function Boo({ title }: { title: string }): JSX.Element {
9+
throw new Error(title);
10+
}
11+
12+
function Bam(): JSX.Element {
13+
const [title] = useState('boom');
14+
return <Boo title={title} />;
15+
}
16+
17+
const TestApp: React.FC<ErrorBoundaryProps> = ({ children, ...props }) => {
18+
const [isError, setError] = React.useState(false);
19+
return (
20+
<ErrorBoundary
21+
{...props}
22+
onReset={(...args) => {
23+
setError(false);
24+
if (props.onReset) {
25+
props.onReset(...args);
26+
}
27+
}}
28+
>
29+
{isError ? <Bam /> : children}
30+
<button
31+
data-testid="errorBtn"
32+
onClick={() => {
33+
setError(true);
34+
}}
35+
/>
36+
</ErrorBoundary>
37+
);
38+
};
39+
40+
describe.only('Integration Test', () => {
41+
it('captures an error and sends it to Sentry', () => {
42+
init({
43+
dsn: '',
44+
beforeSend: event => {
45+
console.log(event);
46+
return event;
47+
},
48+
});
49+
50+
render(
51+
<TestApp fallback={<p>You have hit an error</p>}>
52+
<h1>children</h1>
53+
</TestApp>,
54+
);
55+
56+
const btn = screen.getByTestId('errorBtn');
57+
fireEvent.click(btn);
58+
});
59+
});

0 commit comments

Comments
 (0)