Skip to content

Commit

Permalink
fix(react): Require ReactElement in ErrorBoundary props and render (#…
Browse files Browse the repository at this point in the history
…3857)

Updates the ErrorBoundary fallback type in @sentry/react to require a ReactElement, which matches the `React.isValidElement` check better.
  • Loading branch information
Jonathan Como authored Aug 3, 2021
1 parent 9ca4c5b commit 454893f
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 9 deletions.
24 changes: 16 additions & 8 deletions packages/react/src/errorboundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
withScope,
} from '@sentry/browser';
import { Event } from '@sentry/types';
import { parseSemver } from '@sentry/utils';
import { logger, parseSemver } from '@sentry/utils';
import hoistNonReactStatics from 'hoist-non-react-statics';
import * as React from 'react';

Expand All @@ -21,7 +21,7 @@ export type FallbackRender = (errorData: {
componentStack: string | null;
eventId: string | null;
resetError(): void;
}) => React.ReactNode;
}) => React.ReactElement;

export type ErrorBoundaryProps = {
/** If a Sentry report dialog should be rendered on error */
Expand All @@ -39,7 +39,7 @@ export type ErrorBoundaryProps = {
* the error, the component stack, and an function that resets the error boundary on error.
*
*/
fallback?: React.ReactNode | FallbackRender;
fallback?: React.ReactElement | FallbackRender;
/** Called with the error boundary encounters an error */
onError?(error: Error, componentStack: string, eventId: string): void;
/** Called on componentDidMount() */
Expand Down Expand Up @@ -160,14 +160,22 @@ class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundarySta
const { error, componentStack, eventId } = this.state;

if (error) {
if (React.isValidElement(fallback)) {
return fallback;
}
let element: React.ReactElement | undefined = undefined;
if (typeof fallback === 'function') {
return fallback({ error, componentStack, resetError: this.resetErrorBoundary, eventId }) as FallbackRender;
element = fallback({ error, componentStack, resetError: this.resetErrorBoundary, eventId });
} else {
element = fallback;
}

if (React.isValidElement(element)) {
return element;
}

if (fallback) {
logger.warn('fallback did not produce a valid ReactElement');
}

// Fail gracefully if no fallback provided
// Fail gracefully if no fallback provided or is not valid
return null;
}

Expand Down
12 changes: 11 additions & 1 deletion packages/react/test/errorboundary.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,17 @@ describe('ErrorBoundary', () => {

it('renders null if not given a valid `fallback` prop', () => {
const { container } = render(
<ErrorBoundary fallback={new Error('true')}>
<ErrorBoundary fallback="Not a ReactElement">
<Bam />
</ErrorBoundary>,
);

expect(container.innerHTML).toBe('');
});

it('renders null if not given a valid `fallback` prop function', () => {
const { container } = render(
<ErrorBoundary fallback={() => 'Not a ReactElement'}>
<Bam />
</ErrorBoundary>,
);
Expand Down

0 comments on commit 454893f

Please sign in to comment.