Skip to content

Commit a1915a7

Browse files
committed
feat: [ErrorBoundary] support FallbackComponent props
1 parent 3d91644 commit a1915a7

File tree

3 files changed

+104
-11
lines changed

3 files changed

+104
-11
lines changed
Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,42 @@
11
import React from 'react';
22

3-
export interface ErrorBoundaryProps {
4-
fallback?: React.ReactNode;
5-
}
3+
export type ErrorBoundaryState = {
4+
error: Error | null;
5+
errorInfo: React.ErrorInfo | null;
6+
};
7+
8+
type FallbackProps = ErrorBoundaryState;
9+
10+
export type ErrorBoundaryProps = {
11+
FallbackComponent?: React.ComponentType<FallbackProps>;
12+
[k: string]: any;
13+
};
614

7-
export class ErrorBoundary extends React.Component<ErrorBoundaryProps> {
8-
state = { hasError: false };
15+
export class ErrorBoundary extends React.Component<
16+
React.PropsWithRef<React.PropsWithChildren<ErrorBoundaryProps>>,
17+
ErrorBoundaryState
18+
> {
19+
state = {
20+
error: null,
21+
errorInfo: null,
22+
};
923

10-
static getDerivedStateFromError() {
11-
return { hasError: true };
24+
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
25+
this.setState({ error, errorInfo });
1226
}
1327

1428
render() {
15-
const { fallback, children } = this.props;
16-
const { hasError } = this.state;
29+
const { FallbackComponent, children, ...rest } = this.props;
30+
const { error, errorInfo } = this.state;
1731

18-
if (hasError) {
19-
return fallback || null;
32+
if (errorInfo) {
33+
if (FallbackComponent) {
34+
return <FallbackComponent error={error} errorInfo={errorInfo} {...rest} />;
35+
}
36+
37+
return null;
2038
}
39+
2140
return children;
2241
}
2342
}

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export { Divider } from './components/Divider';
3030
export type { DividerProps } from './components/Divider';
3131
export { Empty } from './components/Empty';
3232
export type { EmptyProps } from './components/Empty';
33+
export { ErrorBoundary } from './components/ErrorBoundary';
34+
export type { ErrorBoundaryProps } from './components/ErrorBoundary';
3335
export { Flex, FlexItem } from './components/Flex';
3436
export type { FlexProps, FlexItemProps } from './components/Flex';
3537
export { Form, FormActions, FormItem } from './components/Form';
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import React from 'react';
2+
import { Meta } from '@storybook/react/types-6-0';
3+
4+
import { ErrorBoundary } from '../../src';
5+
6+
export default {
7+
title: 'ErrorBoundary',
8+
component: ErrorBoundary,
9+
decorators: [
10+
(Story) => (
11+
<div>
12+
<h3>My title</h3>
13+
<Story />
14+
</div>
15+
),
16+
],
17+
} as Meta;
18+
19+
export const WillCrashed = () => <BuggyCounter />;
20+
21+
export const NoFallback = () => (
22+
<ErrorBoundary>
23+
<BuggyCounter />
24+
</ErrorBoundary>
25+
);
26+
27+
export const FallbackComponent = () => (
28+
<div>
29+
<ErrorBoundary FallbackComponent={ErrorFallback}>
30+
<BuggyCounter />
31+
</ErrorBoundary>
32+
</div>
33+
);
34+
35+
export const NoError = (args) => (
36+
<ErrorBoundary {...args}>
37+
<p>no error</p>
38+
</ErrorBoundary>
39+
);
40+
41+
// https://codepen.io/gaearon/pen/wqvxGa?editors=0010
42+
class BuggyCounter extends React.Component<{}, { counter: number }> {
43+
state = { counter: 0 };
44+
45+
handleClick = () => {
46+
this.setState(({ counter }) => ({
47+
counter: counter + 1,
48+
}));
49+
};
50+
51+
render() {
52+
const { counter } = this.state;
53+
if (counter === 5) {
54+
// Simulate a JS error
55+
throw new Error('I crashed!');
56+
}
57+
return <h1 onClick={this.handleClick}>{counter}</h1>;
58+
}
59+
}
60+
61+
function ErrorFallback({ error, errorInfo }) {
62+
return (
63+
<div>
64+
<h2>Something went wrong.</h2>
65+
<details style={{ whiteSpace: 'pre-wrap' }}>
66+
{error && error.toString()}
67+
<br />
68+
{errorInfo.componentStack}
69+
</details>
70+
</div>
71+
);
72+
}

0 commit comments

Comments
 (0)