Skip to content

Commit 21fb832

Browse files
lottamusP0lip
authored andcommitted
feat: add error boundary
1 parent 8a16999 commit 21fb832

File tree

5 files changed

+31
-24
lines changed

5 files changed

+31
-24
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@
4848
"lodash": "^4.17.11",
4949
"mobx-react-lite": "^1.3.1",
5050
"pluralize": "^7.0.0",
51-
"json-schema-merge-allof": "^0.6.0"
51+
"json-schema-merge-allof": "^0.6.0",
52+
"react-error-boundary": "^1.2.5"
5253
},
5354
"devDependencies": {
5455
"@sambego/storybook-state": "^1.3.4",

src/components/JsonSchemaViewer.tsx

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,17 @@ import { TreeStore } from '@stoplight/tree-list';
22
import { Omit } from '@stoplight/types';
33
import { runInAction } from 'mobx';
44
import * as React from 'react';
5+
import ErrorBoundary, { ErrorBoundaryProps, FallbackProps } from 'react-error-boundary';
56

67
import { isSchemaViewerEmpty, renderSchema } from '../utils';
78
import { ISchemaTree, SchemaTree } from './SchemaTree';
89

9-
export interface IJsonSchemaViewer extends Omit<ISchemaTree, 'treeStore'> {
10+
export interface IJsonSchemaViewer extends ErrorBoundaryProps, Omit<ISchemaTree, 'treeStore'> {
1011
emptyText?: string;
1112
defaultExpandedDepth?: number;
1213
}
1314

14-
export interface IJsonSchemaViewerState {
15-
error: null | string;
16-
}
17-
18-
export class JsonSchemaViewer extends React.PureComponent<IJsonSchemaViewer, IJsonSchemaViewerState> {
19-
public state = {
20-
error: null,
21-
};
22-
15+
class JsonSchemaViewerComponent extends React.PureComponent<IJsonSchemaViewer> {
2316
protected treeStore: TreeStore;
2417

2518
constructor(props: IJsonSchemaViewer) {
@@ -31,11 +24,6 @@ export class JsonSchemaViewer extends React.PureComponent<IJsonSchemaViewer, IJs
3124
});
3225
}
3326

34-
// there is no error hook yet, see https://reactjs.org/docs/hooks-faq.html#how-do-lifecycle-methods-correspond-to-hooks
35-
public static getDerivedStateFromError(error: Error): { error: IJsonSchemaViewerState['error'] } {
36-
return { error: `Error rendering schema. ${error.message}` };
37-
}
38-
3927
protected get expandedDepth(): number {
4028
if (this.props.expanded) {
4129
return 2 ** 31 - 3; // tree-list kind of equivalent of expanded: all
@@ -67,13 +55,8 @@ export class JsonSchemaViewer extends React.PureComponent<IJsonSchemaViewer, IJs
6755
public render() {
6856
const {
6957
props: { emptyText = 'No schema defined', name, schema, expanded, defaultExpandedDepth, ...props },
70-
state: { error },
7158
} = this;
7259

73-
if (error) {
74-
return <div>{error}</div>;
75-
}
76-
7760
// an empty array or object is still a valid response, schema is ONLY really empty when a combiner type has no information
7861
if (isSchemaViewerEmpty(schema)) {
7962
return <div>{emptyText}</div>;
@@ -82,3 +65,25 @@ export class JsonSchemaViewer extends React.PureComponent<IJsonSchemaViewer, IJs
8265
return <SchemaTree expanded={expanded} name={name} schema={schema} treeStore={this.treeStore} {...props} />;
8366
}
8467
}
68+
69+
const JsonSchemaFallbackComponent: React.FunctionComponent<FallbackProps> = ({ error }) => {
70+
return (
71+
<div className="p-4">
72+
<b>Error</b>
73+
{error && `: ${error.message}`}
74+
</div>
75+
);
76+
};
77+
78+
export const JsonSchemaViewer: React.FunctionComponent<IJsonSchemaViewer> = ({
79+
onError,
80+
FallbackComponent = JsonSchemaFallbackComponent,
81+
...props
82+
}) => {
83+
return (
84+
<ErrorBoundary onError={onError} FallbackComponent={FallbackComponent}>
85+
<JsonSchemaViewerComponent {...props} />
86+
</ErrorBoundary>
87+
);
88+
};
89+
JsonSchemaViewer.displayName = 'JsonSchemaViewer';

src/components/SchemaTree.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { DetailDialog, ISchemaRow, MaskedSchema, SchemaRow, TopBar } from './';
1515

1616
const canDrag = () => false;
1717

18-
export interface ISchemaTree extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect'>, IMasking {
18+
export interface ISchemaTree extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect' | 'onError'>, IMasking {
1919
name?: string;
2020
dereferencedSchema?: JSONSchema4;
2121
schema: JSONSchema4;

src/utils/isSchemaViewerEmpty.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import { get as _get, isEmpty as _isEmpty } from 'lodash';
44
const combinerTypes = ['allOf', 'oneOf', 'anyOf'];
55

66
export const isSchemaViewerEmpty = (schema: ISchema) => {
7-
const objectKeys = Object.keys(schema);
7+
if (typeof schema !== 'object' || schema === null) return true;
88

9+
const objectKeys = Object.keys(schema);
910
if (objectKeys.length === 1 && combinerTypes.includes(objectKeys[0])) {
1011
return _isEmpty(_get(schema, objectKeys[0], []));
1112
}

yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12003,7 +12003,7 @@ react-draggable@^3.1.1, react-draggable@^3.3.0:
1200312003

1200412004
react-error-boundary@^1.2.5:
1200512005
version "1.2.5"
12006-
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-1.2.5.tgz#a362cb799d2e58ff8f114f7c4bc25677ce4e4149"
12006+
resolved "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-1.2.5.tgz#a362cb799d2e58ff8f114f7c4bc25677ce4e4149"
1200712007
integrity sha512-5CPSeLJA2igJNppAgFRwnTL9aK3ojenk65enNzhVyoxYNbHpIJXnChUO7+4vPhkncRA9wvQMXq6Azp2XeXd+iQ==
1200812008

1200912009
react-error-overlay@^5.1.4:

0 commit comments

Comments
 (0)