React 错误边界不能防止 cra 应用程序崩溃
React error boundary doesn't prevent cra app from crashing
我想创建一个错误边界来防止我的整个应用程序崩溃,而是通知用户出现问题并让他可以选择重新加载页面。我的错误边界组件:
import React, { Fragment, PureComponent } from "react";
import { withRouter, RouteComponentProps } from "react-router";
type Props = RouteComponentProps;
type State = { hasError: boolean; };
class RootErrorBoundary extends PureComponent<Props, State> {
state: State = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
reloadPage = () => {
this.setState({ hasError: false });
const { history } = this.props;
history.go(0);
};
renderOnError = () => {
return (
<Fragment>
Somthing went wrong!
<button onClick={this.reloadPage}>Click here to reload</button>
</Fragment>
);
};
render() {
if (this.state.hasError) {
return this.renderOnError();
}
return this.props.children;
}
}
export default withRouter(RootErrorBoundary);
我是这样实现的:
// index.jsx
// ...
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<StylesProvider injectFirst>
<ConnectedThemeProvider>
<RootErrorBoundary>
<App />
</RootErrorBoundary>
</ConnectedThemeProvider>
</StylesProvider>
</Router>
</Provider>,
rootElement
);
然后,在我的 App 组件树深处的某个地方,我定义了一个函数来手动触发错误(用于 testing/prototyping 目的):
const [hasError, setHasError] = useState(false);
(window as any).kaboom = () => setHasError(true);
if (hasError) {
setHasError(false);
throw new Error("CUSTOM ERROR");
}
当我从控制台调用 window.kaboom()
时,我的错误边界会正确触发。但是一旦我点击重新加载按钮,而不是刷新页面,同样的错误就会被 cra 的错误覆盖捕获并打印堆栈跟踪:
Error: CUSTOM ERROR
TemplateTable
FILE_WITH_ERROR.tsx:96
93 | (window as any).kaboom = () => setHasError(true);
94 | if (hasError) {
95 | setHasError(false);
> 96 | throw new Error("CUSTOM ERROR");
| ^
97 | }
98 |
99 | return (
View compiled
▶ 17 stack frames were collapsed.
TemplateTable.window.kaboom
FILE_WITH_ERROR.tsx:93
90 | );
91 |
92 | const [hasError, setHasError] = useState(false);
> 93 | (window as any).kaboom = () => setHasError(true);
| ^
94 | if (hasError) {
95 | setHasError(false);
96 | throw new Error("CUSTOM ERROR");
View compiled
(anonymous function)
<anonymous>:1:1
这是为什么?我期望我的自定义错误边界能够捕获错误并且不会让它进一步传播。我怎样才能实现我想要的并正确测试我的解决方案?
我的期望错了。在开发模式下无法禁用错误覆盖,捕获错误并不能阻止它。它也不是像我想的那样由单击按钮触发的——无论如何它都会在几秒钟后出现(我只是将它与单击我脑海中的按钮相关联)。
我需要做的就是测试我的边界,当它弹出时按 escape
再次关闭它。
此答案归功于:
我想创建一个错误边界来防止我的整个应用程序崩溃,而是通知用户出现问题并让他可以选择重新加载页面。我的错误边界组件:
import React, { Fragment, PureComponent } from "react";
import { withRouter, RouteComponentProps } from "react-router";
type Props = RouteComponentProps;
type State = { hasError: boolean; };
class RootErrorBoundary extends PureComponent<Props, State> {
state: State = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
reloadPage = () => {
this.setState({ hasError: false });
const { history } = this.props;
history.go(0);
};
renderOnError = () => {
return (
<Fragment>
Somthing went wrong!
<button onClick={this.reloadPage}>Click here to reload</button>
</Fragment>
);
};
render() {
if (this.state.hasError) {
return this.renderOnError();
}
return this.props.children;
}
}
export default withRouter(RootErrorBoundary);
我是这样实现的:
// index.jsx
// ...
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<StylesProvider injectFirst>
<ConnectedThemeProvider>
<RootErrorBoundary>
<App />
</RootErrorBoundary>
</ConnectedThemeProvider>
</StylesProvider>
</Router>
</Provider>,
rootElement
);
然后,在我的 App 组件树深处的某个地方,我定义了一个函数来手动触发错误(用于 testing/prototyping 目的):
const [hasError, setHasError] = useState(false);
(window as any).kaboom = () => setHasError(true);
if (hasError) {
setHasError(false);
throw new Error("CUSTOM ERROR");
}
当我从控制台调用 window.kaboom()
时,我的错误边界会正确触发。但是一旦我点击重新加载按钮,而不是刷新页面,同样的错误就会被 cra 的错误覆盖捕获并打印堆栈跟踪:
Error: CUSTOM ERROR
TemplateTable
FILE_WITH_ERROR.tsx:96
93 | (window as any).kaboom = () => setHasError(true);
94 | if (hasError) {
95 | setHasError(false);
> 96 | throw new Error("CUSTOM ERROR");
| ^
97 | }
98 |
99 | return (
View compiled
▶ 17 stack frames were collapsed.
TemplateTable.window.kaboom
FILE_WITH_ERROR.tsx:93
90 | );
91 |
92 | const [hasError, setHasError] = useState(false);
> 93 | (window as any).kaboom = () => setHasError(true);
| ^
94 | if (hasError) {
95 | setHasError(false);
96 | throw new Error("CUSTOM ERROR");
View compiled
(anonymous function)
<anonymous>:1:1
这是为什么?我期望我的自定义错误边界能够捕获错误并且不会让它进一步传播。我怎样才能实现我想要的并正确测试我的解决方案?
我的期望错了。在开发模式下无法禁用错误覆盖,捕获错误并不能阻止它。它也不是像我想的那样由单击按钮触发的——无论如何它都会在几秒钟后出现(我只是将它与单击我脑海中的按钮相关联)。
我需要做的就是测试我的边界,当它弹出时按 escape
再次关闭它。
此答案归功于: