Skip to content

Commit 7cac80f

Browse files
author
Mark
authored
50-white-screen-on-empty-content-type (#51)
* fix: White screen on empty Content-Type #50 * fix * feat: add error boundary to catch errors * chore: code formatting --------- Co-authored-by: no <no>
1 parent ae32969 commit 7cac80f

File tree

6 files changed

+95
-5
lines changed

6 files changed

+95
-5
lines changed

components/ContentView.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { TextView } from './content-view/TextView';
99
import { ViewMode } from './content-view/viewModes';
1010
import { ViewModeSelect } from './content-view/ViewModeSelect';
1111
import { XMLView } from './content-view/XMLView';
12+
import { withUiErrorBoundary } from '../utils/withUiErrorBoundary';
1213

1314
const useStyles = makeStyles((theme) => ({
1415
contentArea: {
@@ -21,7 +22,7 @@ export interface IContentViewProps {
2122
data: Buffer;
2223
}
2324

24-
export const ContentView: FC<IContentViewProps> = ({ contentType, data }) => {
25+
const ContentViewInner: FC<IContentViewProps> = ({ contentType, data }) => {
2526
const detected = detectType(contentType);
2627
const [viewMode, setViewMode] = useState<ViewMode>(detected.viewType);
2728
useEffect(() => {
@@ -50,3 +51,5 @@ export const ContentView: FC<IContentViewProps> = ({ contentType, data }) => {
5051
</Grid>
5152
);
5253
};
54+
55+
export const ContentView = withUiErrorBoundary(ContentViewInner);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { detectType } from '../detectType';
2+
3+
describe('detectType', function () {
4+
it('should work', function () {
5+
expect(detectType('application/json')).toEqual({
6+
pureType: 'application/json',
7+
viewType: 'json',
8+
});
9+
10+
expect(detectType('application/json; charset=utf-8')).toEqual({
11+
pureType: 'application/json',
12+
viewType: 'json',
13+
});
14+
15+
expect(detectType('application/json; charset=utf-8; foo=bar')).toEqual({
16+
pureType: 'application/json',
17+
viewType: 'json',
18+
});
19+
20+
expect(detectType(null)).toEqual({
21+
pureType: '',
22+
viewType: 'plain',
23+
});
24+
});
25+
});

components/content-view/detectType.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ type ViewType = 'plain' | 'image' | 'json' | 'xml' | 'form';
1010

1111
const plusSuffixRegex = /\+(\w+)/g;
1212

13-
export function detectType(
14-
contentType: string | null
15-
): { pureType: string; viewType: ViewType } {
16-
const [pureType] = contentType?.split(';') ?? [];
13+
export function detectType(contentType: string | null): {
14+
pureType: string;
15+
viewType: ViewType;
16+
} {
17+
const [pureType] = contentType?.split(';') ?? [''];
1718

1819
// https://trac.tools.ietf.org/html/draft-ietf-appsawg-media-type-suffix-regs-02
1920
const plusSuffices = new Set(

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
"react-inspector": "^5.1.0",
111111
"react-redux": "^7.1.1",
112112
"react-splitter-layout": "^4.0.0",
113+
"react-use-error-boundary": "^3.0.0",
113114
"redux": "^4.0.4",
114115
"redux-saga": "^1.1.3",
115116
"reselect": "^4.0.0",

utils/withUiErrorBoundary.tsx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import Button from '@material-ui/core/Button';
2+
import makeStyles from '@material-ui/core/styles/makeStyles';
3+
import Typography from '@material-ui/core/Typography';
4+
import React, { FC } from 'react';
5+
import { useErrorBoundary, withErrorBoundary } from 'react-use-error-boundary';
6+
7+
const useErrorBoundaryStyles = makeStyles((_theme) => ({
8+
errorContainer: {
9+
display : 'flex',
10+
flexDirection : 'column',
11+
justifyContent: 'center',
12+
alignItems : 'center',
13+
height : '100%',
14+
},
15+
errorMessage: {
16+
textAlign: 'center',
17+
},
18+
}));
19+
export function withUiErrorBoundary<Props>(Component: FC<Props>) {
20+
const WithUiErrorBoundary: FC<Props> = withErrorBoundary((props) => {
21+
const [error, retry] = useErrorBoundary();
22+
const classes = useErrorBoundaryStyles();
23+
if (error) {
24+
return (
25+
<div className={classes.errorContainer}>
26+
<Typography
27+
variant="h5"
28+
color="textPrimary"
29+
className={classes.errorMessage}
30+
>
31+
Something went wrong...
32+
</Typography>
33+
<div>
34+
<Button
35+
variant="contained"
36+
color="primary"
37+
onClick={retry}
38+
>
39+
Retry
40+
</Button>
41+
</div>
42+
<Typography
43+
variant="body1"
44+
color="textPrimary"
45+
className={classes.errorMessage}
46+
>
47+
<pre>{(error as Error).message}</pre>
48+
</Typography>
49+
</div>
50+
);
51+
}
52+
return <Component {...props} />;
53+
});
54+
return WithUiErrorBoundary;
55+
}

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11528,6 +11528,11 @@ react-transition-group@^4.4.0:
1152811528
loose-envify "^1.4.0"
1152911529
prop-types "^15.6.2"
1153011530

11531+
react-use-error-boundary@^3.0.0:
11532+
version "3.0.0"
11533+
resolved "https://registry.yarnpkg.com/react-use-error-boundary/-/react-use-error-boundary-3.0.0.tgz#c5b44acf9ab376f59a219d740ac372b05aba6240"
11534+
integrity sha512-5urkfyU3ZzInEMSHe1gxtDzlQAHs0krTt0V6h8H2L5nXhDKq3OYXnCs9lGHDkEkYvLmsphw8ap5g8uYfvrkJng==
11535+
1153111536
react@^16.9.0:
1153211537
version "16.14.0"
1153311538
resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d"

0 commit comments

Comments
 (0)