|
1 | 1 | import React, { ErrorInfo } from "react";
|
| 2 | +import { Element as ElementType } from "~/types"; |
| 3 | + |
| 4 | +type State = |
| 5 | + | { |
| 6 | + hasError: true; |
| 7 | + error: Error; |
| 8 | + } |
| 9 | + | { hasError: false; error: undefined }; |
2 | 10 |
|
3 |
| -interface State { |
4 |
| - hasError: boolean; |
5 |
| -} |
6 | 11 | interface Props {
|
| 12 | + element: ElementType; |
7 | 13 | [key: string]: any;
|
8 | 14 | }
|
| 15 | + |
| 16 | +const displayNone = { |
| 17 | + display: "none" |
| 18 | +}; |
| 19 | + |
| 20 | +declare global { |
| 21 | + // eslint-disable-next-line |
| 22 | + namespace JSX { |
| 23 | + interface IntrinsicElements { |
| 24 | + "pb-element-error": any; |
| 25 | + } |
| 26 | + } |
| 27 | +} |
| 28 | + |
9 | 29 | class ErrorBoundary extends React.Component<Props, State> {
|
10 | 30 | constructor(props: Props) {
|
11 | 31 | super(props);
|
12 | 32 | this.state = {
|
13 |
| - hasError: false |
| 33 | + hasError: false, |
| 34 | + error: undefined |
14 | 35 | };
|
15 | 36 | }
|
16 | 37 |
|
17 |
| - static getDerivedStateFromError() { |
| 38 | + static getDerivedStateFromError(error: Error) { |
18 | 39 | // Update state so the next render will show the fallback UI.
|
19 | 40 | return {
|
20 |
| - hasError: true |
| 41 | + hasError: true, |
| 42 | + error |
21 | 43 | };
|
22 | 44 | }
|
23 | 45 |
|
24 | 46 | public override componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
25 |
| - console.log("An error occurred while rendering a page element:"); |
26 |
| - console.log(error, errorInfo); |
| 47 | + const { element } = this.props; |
| 48 | + console.groupCollapsed( |
| 49 | + `%cELEMENT ERROR%c: An error occurred while rendering page element "${element.id}" of type "${element.type}".`, |
| 50 | + "color:red", |
| 51 | + "color:default" |
| 52 | + ); |
| 53 | + console.log("element", element); |
| 54 | + console.error(error, errorInfo); |
| 55 | + console.groupEnd(); |
27 | 56 | }
|
28 | 57 |
|
29 | 58 | public override render() {
|
30 | 59 | if (this.state.hasError) {
|
31 |
| - // You can render any custom fallback UI |
32 |
| - return <h1>Something went wrong.</h1>; |
| 60 | + const elementData = { |
| 61 | + id: this.props.element.id, |
| 62 | + type: this.props.element.type, |
| 63 | + error: this.state.error.message |
| 64 | + }; |
| 65 | + |
| 66 | + return ( |
| 67 | + <pb-element-error style={displayNone}> |
| 68 | + {JSON.stringify(elementData)} |
| 69 | + </pb-element-error> |
| 70 | + ); |
33 | 71 | }
|
34 | 72 |
|
35 | 73 | return this.props.children;
|
|
0 commit comments