React.js - 错误边界
React.js - ErrorBoundary
我不太确定,如果我完全理解 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
组件,这样就只显示出错的组件,不显示整个app?
非常感谢您提前对此做出任何解释!
PS:我也想知道,为什么我不能在我的 ErrorBoundary
组件中同时使用 getDerivedStateFromError
和 componentDidCatch
方法。当在 ErrorBoundary
中定义 getDerivedStateFromError
方法时,从未调用方法 componentDidCatch
:
static getDerivedStateFromError(error) {
return { hasError: true };
}
...但据我所知,仅使用 componentDidCatch
.
即可正常工作
由于错误发生在 navbar.component.js
中,ErrorBoundary
必须存在于其 parent 层次结构中的某处。目前,您将其用作 navbar.component.js
的 child
将 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>
)
}
}
我不太确定,如果我完全理解 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
组件,这样就只显示出错的组件,不显示整个app?
非常感谢您提前对此做出任何解释!
PS:我也想知道,为什么我不能在我的 ErrorBoundary
组件中同时使用 getDerivedStateFromError
和 componentDidCatch
方法。当在 ErrorBoundary
中定义 getDerivedStateFromError
方法时,从未调用方法 componentDidCatch
:
static getDerivedStateFromError(error) {
return { hasError: true };
}
...但据我所知,仅使用 componentDidCatch
.
由于错误发生在 navbar.component.js
中,ErrorBoundary
必须存在于其 parent 层次结构中的某处。目前,您将其用作 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>
)
}
}