improved error boundary

This commit is contained in:
Jan Prochazka 2021-01-25 17:20:17 +01:00
parent 7e39b8c2a0
commit 72cc510c64
2 changed files with 101 additions and 45 deletions

View File

@ -16,7 +16,7 @@ import DragAndDropFileTarget from './DragAndDropFileTarget';
import { useUploadsZone } from './utility/UploadsProvider'; import { useUploadsZone } from './utility/UploadsProvider';
import useTheme from './theme/useTheme'; import useTheme from './theme/useTheme';
import { MenuLayer } from './modals/showMenu'; import { MenuLayer } from './modals/showMenu';
import ErrorBoundary from './utility/ErrorBoundary'; import ErrorBoundary, { ErrorBoundaryTest } from './utility/ErrorBoundary';
const BodyDiv = styled.div` const BodyDiv = styled.div`
position: fixed; position: fixed;
@ -106,39 +106,41 @@ export default function Screen() {
return ( return (
<div {...getRootProps()}> <div {...getRootProps()}>
<ToolBarDiv theme={theme}> <ErrorBoundary>
<ToolBar toolbarPortalRef={toolbarPortalRef} /> <ToolBarDiv theme={theme}>
</ToolBarDiv> <ToolBar toolbarPortalRef={toolbarPortalRef} />
<IconBar theme={theme}> </ToolBarDiv>
<WidgetIconPanel /> <IconBar theme={theme}>
</IconBar> <WidgetIconPanel />
{!!currentWidget && ( </IconBar>
<LeftPanel theme={theme}> {!!currentWidget && (
<ErrorBoundary> <LeftPanel theme={theme}>
<WidgetContainer /> <ErrorBoundary>
</ErrorBoundary> <WidgetContainer />
</LeftPanel> </ErrorBoundary>
)} </LeftPanel>
{!!currentWidget && ( )}
<ScreenHorizontalSplitHandle {!!currentWidget && (
onMouseDown={onSplitDown} <ScreenHorizontalSplitHandle
theme={theme} onMouseDown={onSplitDown}
style={{ left: leftPanelWidth + dimensions.widgetMenu.iconSize }} theme={theme}
/> style={{ left: leftPanelWidth + dimensions.widgetMenu.iconSize }}
)} />
<TabsPanelContainer contentLeft={contentLeft} theme={theme}> )}
<TabsPanel></TabsPanel> <TabsPanelContainer contentLeft={contentLeft} theme={theme}>
</TabsPanelContainer> <TabsPanel></TabsPanel>
<BodyDiv contentLeft={contentLeft} theme={theme}> </TabsPanelContainer>
<TabContent toolbarPortalRef={toolbarPortalRef} /> <BodyDiv contentLeft={contentLeft} theme={theme}>
</BodyDiv> <TabContent toolbarPortalRef={toolbarPortalRef} />
<StausBarContainer theme={theme}> </BodyDiv>
<StatusBar /> <StausBarContainer theme={theme}>
</StausBarContainer> <StatusBar />
<ModalLayer /> </StausBarContainer>
<MenuLayer /> <ModalLayer />
<MenuLayer />
<DragAndDropFileTarget inputProps={getInputProps()} isDragActive={isDragActive} /> <DragAndDropFileTarget inputProps={getInputProps()} isDragActive={isDragActive} />
</ErrorBoundary>
</div> </div>
); );
} }

View File

@ -1,5 +1,58 @@
import React from 'react'; import React from 'react';
import _ from 'lodash';
import ErrorInfo from '../widgets/ErrorInfo'; import ErrorInfo from '../widgets/ErrorInfo';
import styled from 'styled-components';
import localforage from 'localforage';
import FormStyledButton from '../widgets/FormStyledButton';
const Stack = styled.pre`
margin-left: 20px;
`;
const WideButton = styled(FormStyledButton)`
width: 150px;
`;
const Info = styled.div`
margin: 20px;
`;
export function ErrorScreen({ error }) {
let message;
try {
message = 'Error: ' + (error.message || error).toString();
} catch (e) {
message = 'DbGate internal error detected';
}
const handleReload = () => {
window.location.reload();
};
const handleClearReload = async () => {
localStorage.clear();
try {
await localforage.clear();
} catch (err) {
console.error('Error clearing app data', err);
}
window.location.reload();
};
return (
<div>
<ErrorInfo message={message} />
<WideButton type="button" value="Reload app" onClick={handleReload} />
<WideButton type="button" value="Clear and reload" onClick={handleClearReload} />
<Info>
If reloading doesn&apos;t help, you can try to clear all browser data (opened tabs, history of opened windows)
and reload app. Your connections and saved files are not touched by this clear operation. <br />
If you see this error in the tab, closing the tab should solve the problem.
</Info>
<Stack>{_.isString(error.stack) ? error.stack : null}</Stack>
</div>
);
}
export default class ErrorBoundary extends React.Component { export default class ErrorBoundary extends React.Component {
constructor(props) { constructor(props) {
@ -23,19 +76,20 @@ export default class ErrorBoundary extends React.Component {
} }
render() { render() {
if (this.state.hasError) { if (this.state.hasError) {
let message; return <ErrorScreen error={this.state.error} />;
try {
message = (this.state.error.message || this.state.error).toString();
} catch (e) {
message = 'Error detected';
}
// You can render any custom fallback UI
return (
<div>
<ErrorInfo message={message} />;
</div>
);
} }
return this.props.children; return this.props.children;
} }
} }
export function ErrorBoundaryTest({ children }) {
let error;
try {
const x = 1;
// @ts-ignore
x.log();
} catch (err) {
error = err;
}
return <ErrorScreen error={error} />;
}