Skip to content

Commit e11b0c1

Browse files
committed
feat: add error boundary
1 parent 1eb652b commit e11b0c1

2 files changed

Lines changed: 95 additions & 1 deletion

File tree

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import React, { Component } from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
const styles = {
5+
container: {
6+
padding: '1.5rem',
7+
fontFamily: 'system-ui, sans-serif',
8+
color: '#1a1a1a',
9+
backgroundColor: '#fff',
10+
minHeight: '100vh',
11+
boxSizing: 'border-box',
12+
},
13+
heading: {
14+
margin: '0 0 1rem',
15+
fontSize: '1.25rem',
16+
},
17+
message: {
18+
margin: '0 0 1rem',
19+
padding: '1rem',
20+
backgroundColor: '#fef2f2',
21+
border: '1px solid #fecaca',
22+
borderRadius: '4px',
23+
whiteSpace: 'pre-wrap',
24+
wordBreak: 'break-word',
25+
fontSize: '0.875rem',
26+
lineHeight: 1.5,
27+
},
28+
stack: {
29+
margin: '0 0 1.5rem',
30+
padding: '1rem',
31+
backgroundColor: '#f5f5f5',
32+
border: '1px solid #e5e5e5',
33+
borderRadius: '4px',
34+
whiteSpace: 'pre-wrap',
35+
wordBreak: 'break-word',
36+
fontSize: '0.75rem',
37+
lineHeight: 1.4,
38+
overflow: 'auto',
39+
},
40+
button: {
41+
padding: '0.625rem 1.25rem',
42+
fontSize: '1rem',
43+
cursor: 'pointer',
44+
},
45+
};
46+
47+
class ErrorBoundary extends Component {
48+
constructor(props) {
49+
super(props);
50+
this.state = { error: null };
51+
}
52+
53+
static getDerivedStateFromError(error) {
54+
return { error };
55+
}
56+
57+
componentDidCatch(error, errorInfo) {
58+
console.error(error, errorInfo);
59+
}
60+
61+
render() {
62+
const { error } = this.state;
63+
const { children } = this.props;
64+
65+
if (!error) {
66+
return children;
67+
}
68+
69+
return (
70+
<div style={styles.container}>
71+
<h1 style={styles.heading}>Something went wrong</h1>
72+
<pre style={styles.message}>{error.toString()}</pre>
73+
{error.stack && <pre style={styles.stack}>{error.stack}</pre>}
74+
<button
75+
type="button"
76+
style={styles.button}
77+
onClick={() => window.location.reload()}
78+
>
79+
Reload
80+
</button>
81+
</div>
82+
);
83+
}
84+
}
85+
86+
ErrorBoundary.propTypes = {
87+
children: PropTypes.node.isRequired,
88+
};
89+
90+
export default ErrorBoundary;

client/src/containers/Root.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@ import React from 'react';
22
import { Provider } from 'react-redux';
33
import { BrowserRouter as Router } from 'react-router-dom';
44

5+
import ErrorBoundary from '../components/ErrorBoundary';
6+
57
const Root = (App, store) => (
68
<Provider store={store}>
79
<Router>
8-
<App />
10+
<ErrorBoundary>
11+
<App />
12+
</ErrorBoundary>
913
</Router>
1014
</Provider>
1115
);

0 commit comments

Comments
 (0)