问题描述
我不太确定,我是否完全理解 React ErrorBoundary
的概念。
我需要说的是,我实际上想开始使用 ErrorBoundary,但我是第一次使用它。
所以我创建了一个 ErrorBoundary
组件:
import React,{ Component } from "react";
import * as Data from '../../backend/data';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error,stackTrace) {
this.setState({ hasError: true });
console.log(error,stackTrace);
// Send error to backend
Data.trackerror(error,stackTrace.componentStack,this.props.component,this.props.location,this.props.guestLandingPage?.identifier_token,this.props.user?.id);
}
render() {
if (this.state.hasError) {
return this.props.fallbackUI;
}
return this.props.children;
}
}
export default ErrorBoundary;
现在我尝试在我的 app.container.js
中使用它(我不会复制它的整个代码,只会复制它的必要部分):
...
import NavBarComponent from './components/navbar.component';
import ErrorBoundary from './components/error/error.component';
import FallbackUI from './components/error/standardFallback.component';
...
class App extends Component {
...
render() {
const View = this.importView();
return (
<ErrorBoundary
location={"builder"}
component={"app.container.js"}
user={this.props.user}
fallbackUI={<FallbackUI />}
>
<Wrap>
<NavBarComponent
key={"navBarComponent"}
/>
...
</Wrap>
...
</ErrorBoundary>
)
}
}
然后我开始手动创建一个错误。我在 navbar.component.js
中添加了一个变量,该变量不存在并导致抛出错误。
到目前为止效果很好。错误正在发送到后端并显示我的后备 UI 组件。 到目前为止,一切都很好。
然而,现在我不想在顶层捕获错误,而是在单个组件中捕获错误,以便应用程序仍然可用并且错误消息仅在出现错误时显示在单个组件中。
因此,我现在已将 ErrorBoundary
组件移至 navbar.component.js
(并将其从 app.container.js
中删除)。
class NavBarComponent extends Component {
...
render() {
return (
<ErrorBoundary
location={"builder"}
component={"navbar.component.js"}
user={this.props.user}
fallbackUI={<FallbackUI />}
>
<Nav className="navbar navbar-expand-lg navbar-light">
...
</Nav>
</ErrorBoundary>
);
}
}
...期待相同的结果,但仅在显示导航栏的地方显示我的后备 UI 组件。
但实际上结果是,ErrorBoundary
在移动到导航栏时根本没有被触发。
为什么?是不是不能把ErrorBoundary
组件添加到每个组件本身,这样只有出现错误的组件不会显示,而不是整个应用程序?
非常感谢您提前对此做出任何解释!
PS:我也想知道,为什么我不能在我的 getDerivedStateFromError
组件中同时使用 componentDidCatch
和 ErrorBoundary
方法。在 getDerivedStateFromError
中定义 ErrorBoundary
方法时,从未调用方法 componentDidCatch
:
static getDerivedStateFromError(error) {
return { hasError: true };
}
...但据我所知,仅使用 componentDidCatch
即可正常工作。
解决方法
由于错误发生在 navbar.component.js
内,因此 ErrorBoundary
必须存在于其父层次结构中的某处。目前,您将其用作 navbar.component.js
将 ErrorBoundary 的用法更新到下面应该会像您期望的那样工作
class App extends Component {
...
render() {
const View = this.importView();
return (
<Wrap>
<ErrorBoundary
location={"builder"}
component={"app.container.js"}
user={this.props.user}
fallbackUI={<FallbackUI />}
>
<NavBarComponent
key={"navBarComponent"}
/>
</ErrorBoundary>
...
</Wrap>
...
)
}
}
您还可以通过用 ErrorBoundary 包装组件来导出组件,这样您就不必在渲染组件的任何地方都这样做
export default ({location,user,...props}) => {
return (
<ErrorBoundary
location={location}
component={"navbar.component.js"}
user={user}
fallbackUI={<FallbackUI />}
>
<NavBarComponent
key={"navBarComponent"}
{...props}
/>
</ErrorBoundary>
)
}
并像使用它一样
class App extends Component {
...
render() {
const View = this.importView();
return (
<Wrap>
<NavBarComponent
location={"builder"}
user={this.props.user}
key={"navBarComponent"}
/>
...
</Wrap>
)
}
}