Skip to content

Commit 9fc0884

Browse files
committed
feat(react): Add render key option
1 parent 238357f commit 9fc0884

File tree

2 files changed

+27
-11
lines changed

2 files changed

+27
-11
lines changed

packages/react/src/errorboundary.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,21 @@ export type ErrorBoundaryProps = {
99
showDialog?: boolean;
1010
dialogOptions?: Sentry.ReportDialogOptions;
1111
fallback?: React.ReactNode;
12-
fallbackRender?(error: Error | null, componentStack: string | null, resetErrorBoundary: () => void): React.ReactNode;
12+
renderKey?: string | number;
13+
fallbackRender?(fallback: {
14+
error: Error | null;
15+
componentStack: string | null;
16+
resetError(): void;
17+
}): React.ReactNode;
1318
onError?(error: Error, componentStack: string): void;
1419
onMount?(): void;
1520
onReset?(error: Error | null, componentStack: string | null): void;
1621
onUnmount?(error: Error | null, componentStack: string | null): void;
1722
};
1823

1924
type ErrorBoundaryState = {
20-
error: Error | null;
2125
componentStack: string | null;
26+
error: Error | null;
2227
};
2328

2429
const INITIAL_STATE = {
@@ -51,6 +56,17 @@ class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundarySta
5156
}
5257
}
5358

59+
public componentDidUpdate(prevProps: ErrorBoundaryProps): void {
60+
const { error } = this.state;
61+
const { renderKey, onReset } = this.props;
62+
if (error !== null && !Object.is(renderKey, prevProps.renderKey)) {
63+
if (onReset) {
64+
onReset(this.state.error, this.state.componentStack);
65+
}
66+
this.setState(INITIAL_STATE);
67+
}
68+
}
69+
5470
public componentWillUnmount(): void {
5571
const { error, componentStack } = this.state;
5672
const { onUnmount } = this.props;
@@ -73,7 +89,7 @@ class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundarySta
7389

7490
if (error) {
7591
if (typeof fallbackRender === 'function') {
76-
return fallbackRender(error, componentStack, this.resetErrorBoundary);
92+
return fallbackRender({ error, componentStack, resetError: this.resetErrorBoundary });
7793
}
7894
if (React.isValidElement(fallback)) {
7995
return fallback;

packages/react/test/errorboundary.test.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,11 @@ describe('ErrorBoundary', () => {
140140
let compStack = '';
141141
const { baseElement } = render(
142142
<TestApp
143-
fallbackRender={(error: Error, componentStack: string) => {
144-
errorString = error.toString();
145-
compStack = componentStack;
143+
fallbackRender={({ error, componentStack }) => {
144+
if (error && componentStack) {
145+
errorString = error.toString();
146+
compStack = componentStack;
147+
}
146148
return <div>Fallback here</div>;
147149
}}
148150
>
@@ -209,14 +211,12 @@ describe('ErrorBoundary', () => {
209211
expect(mockShowReportDialog).toHaveBeenCalledWith(options);
210212
});
211213

212-
it('it resets to initial state when reset', async () => {
214+
it('resets to initial state when reset', () => {
213215
const mockOnReset = jest.fn();
214-
const { baseElement, debug } = render(
216+
const { baseElement } = render(
215217
<TestApp
216218
onReset={mockOnReset}
217-
fallbackRender={(_, __, resetErrorBoundary: () => void) => (
218-
<button data-testid="reset" onClick={resetErrorBoundary} />
219-
)}
219+
fallbackRender={({ resetError }) => <button data-testid="reset" onClick={resetError} />}
220220
>
221221
<h1>children</h1>
222222
</TestApp>,

0 commit comments

Comments
 (0)