From 62598b32cff3a000bac171dcd621191f9a2f0c1c Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 22 Sep 2021 14:44:19 -0400 Subject: [PATCH 1/4] ref(react): Rely on error.cause to link ErrorBoundary errors --- packages/react/src/errorboundary.tsx | 44 +++----------- .../test/errorboundary-integration.test.tsx | 59 +++++++++++++++++++ 2 files changed, 68 insertions(+), 35 deletions(-) create mode 100644 packages/react/test/errorboundary-integration.test.tsx diff --git a/packages/react/src/errorboundary.tsx b/packages/react/src/errorboundary.tsx index 162bb543b99b..b843b5f5d589 100644 --- a/packages/react/src/errorboundary.tsx +++ b/packages/react/src/errorboundary.tsx @@ -1,13 +1,4 @@ -import { - captureEvent, - captureException, - eventFromException, - ReportDialogOptions, - Scope, - showReportDialog, - withScope, -} from '@sentry/browser'; -import { Event } from '@sentry/types'; +import { captureException, ReportDialogOptions, Scope, showReportDialog, withScope } from '@sentry/browser'; import { logger, parseSemver } from '@sentry/utils'; import hoistNonReactStatics from 'hoist-non-react-statics'; import * as React from 'react'; @@ -71,31 +62,14 @@ const INITIAL_STATE = { * @param error An error captured by React Error Boundary * @param componentStack The component stacktrace */ -function captureReactErrorBoundaryError(error: Error, componentStack: string): string { - const errorBoundaryError = new Error(error.message); - errorBoundaryError.name = `React ErrorBoundary ${errorBoundaryError.name}`; - errorBoundaryError.stack = componentStack; - - let errorBoundaryEvent: Event = {}; - void eventFromException({}, errorBoundaryError).then(e => { - errorBoundaryEvent = e; - }); - - if ( - errorBoundaryEvent.exception && - Array.isArray(errorBoundaryEvent.exception.values) && - reactVersion.major && - reactVersion.major >= 17 - ) { - let originalEvent: Event = {}; - void eventFromException({}, error).then(e => { - originalEvent = e; - }); - if (originalEvent.exception && Array.isArray(originalEvent.exception.values)) { - originalEvent.exception.values = [...errorBoundaryEvent.exception.values, ...originalEvent.exception.values]; - } - - return captureEvent(originalEvent); +function captureReactErrorBoundaryError(error: Error & { cause?: Error }, componentStack: string): string { + if (reactVersion.major && reactVersion.major >= 17) { + const errorBoundaryError = new Error(error.message); + errorBoundaryError.name = `React ErrorBoundary ${errorBoundaryError.name}`; + errorBoundaryError.stack = componentStack; + + error.cause = errorBoundaryError; + return captureException(error); } return captureException(error, { contexts: { react: { componentStack } } }); diff --git a/packages/react/test/errorboundary-integration.test.tsx b/packages/react/test/errorboundary-integration.test.tsx new file mode 100644 index 000000000000..4dc3b117f9bc --- /dev/null +++ b/packages/react/test/errorboundary-integration.test.tsx @@ -0,0 +1,59 @@ +import { fireEvent, render, screen } from '@testing-library/react'; +import * as React from 'react'; +import { useState } from 'react'; + +import { init } from '../src'; +import { ErrorBoundary, ErrorBoundaryProps } from '../src/errorboundary'; + +function Boo({ title }: { title: string }): JSX.Element { + throw new Error(title); +} + +function Bam(): JSX.Element { + const [title] = useState('boom'); + return ; +} + +const TestApp: React.FC = ({ children, ...props }) => { + const [isError, setError] = React.useState(false); + return ( + { + setError(false); + if (props.onReset) { + props.onReset(...args); + } + }} + > + {isError ? : children} +