forked from Shiloh/remnantchat
feat: add error boundary
This commit is contained in:
parent
69a15443ce
commit
44c328fd1f
74
src/components/ErrorBoundary/ErrorBoundary.tsx
Normal file
74
src/components/ErrorBoundary/ErrorBoundary.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
import { Component, ErrorInfo, ReactNode } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import Alert from '@mui/material/Alert'
|
||||
import Box from '@mui/material/Box'
|
||||
import IconButton from '@mui/material/IconButton'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import CloseIcon from '@mui/icons-material/Close'
|
||||
|
||||
import { routes } from 'config/routes'
|
||||
|
||||
interface Props {
|
||||
children?: ReactNode
|
||||
}
|
||||
|
||||
interface State {
|
||||
error: Error | null
|
||||
showError: boolean
|
||||
}
|
||||
|
||||
// Adapted from https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/error_boundaries/
|
||||
export class ErrorBoundary extends Component<Props, State> {
|
||||
public state: State = {
|
||||
error: null,
|
||||
showError: false,
|
||||
}
|
||||
|
||||
public static getDerivedStateFromError(error: Error): State {
|
||||
return { error, showError: true }
|
||||
}
|
||||
|
||||
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
console.error('Uncaught error:', error, errorInfo)
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (this.state.error && this.state.showError) {
|
||||
const { name, message, stack } = this.state.error
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Alert
|
||||
severity="error"
|
||||
action={
|
||||
<IconButton
|
||||
aria-label="close"
|
||||
color="inherit"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
this.setState({ error: null, showError: false })
|
||||
}}
|
||||
>
|
||||
<Link to={routes.ROOT}>
|
||||
<CloseIcon fontSize="inherit" />
|
||||
</Link>
|
||||
</IconButton>
|
||||
}
|
||||
>
|
||||
<Typography variant="h2">
|
||||
<pre>{name}</pre>
|
||||
</Typography>
|
||||
<Typography variant="h3">
|
||||
<code>{message}</code>
|
||||
</Typography>
|
||||
<pre>{stack}</pre>
|
||||
</Alert>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
return this.props.children
|
||||
}
|
||||
}
|
||||
|
||||
export default ErrorBoundary
|
1
src/components/ErrorBoundary/index.ts
Normal file
1
src/components/ErrorBoundary/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './ErrorBoundary'
|
@ -15,6 +15,7 @@ import { AlertColor } from '@mui/material/Alert'
|
||||
import { ShellContext } from 'contexts/ShellContext'
|
||||
import { SettingsContext } from 'contexts/SettingsContext'
|
||||
import { AlertOptions } from 'models/shell'
|
||||
import { ErrorBoundary } from 'components/ErrorBoundary'
|
||||
|
||||
import { Drawer } from './Drawer'
|
||||
import { UpgradeDialog } from './UpgradeDialog'
|
||||
@ -170,7 +171,10 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
|
||||
theme={theme}
|
||||
userPeerId={userPeerId}
|
||||
/>
|
||||
<RouteContent isDrawerOpen={isDrawerOpen}>{children}</RouteContent>
|
||||
|
||||
<RouteContent isDrawerOpen={isDrawerOpen}>
|
||||
<ErrorBoundary>{children}</ErrorBoundary>
|
||||
</RouteContent>
|
||||
</Box>
|
||||
</ThemeProvider>
|
||||
</ShellContext.Provider>
|
||||
|
@ -1,6 +1,5 @@
|
||||
export enum routes {
|
||||
ABOUT = '/about',
|
||||
HOME = '/home',
|
||||
INDEX_HTML = '/index.html',
|
||||
PUBLIC_ROOM = '/public/:roomId',
|
||||
ROOT = '/',
|
||||
|
Loading…
Reference in New Issue
Block a user