为什么 React 仍然渲染带有 Error Boundary 的子组件

Why React still render the child component with Error Boundary

我使用 React 16Error Boundary 功能: Profile.js

class Profile extends Component {
constructor(props) {
    super(props);
    this.state = {
        // user: {
        //     name: "Ha (Huck) H.K. NGUYEN"
        // }
        user: null
    };
    this.updateUser = this.updateUser.bind(this);
}

updateUser() {
    this.setState({ user: null })
}

render() {
    const { user } = this.state;
    console.log(user);
    return <div className="App">
            {user.name}
            <button onClick={this.updateUser}>
                Update
            </button>
        </div>
}
}

ErrorBoundary.js

class ErrorBoundary extends Component {
constructor(props) {
    super(props);
    this.state = {
        hasError: false
    }
}
componentDidCatch(error, errorInfo) {
    this.setState({ hasError: true });
}
render() {
    const { children } = this.props;
    const { hasError } = this.state;
    if (hasError) {
        return <HasError />
    }
    return children
}
}

App.js

class App extends Component {
render() {
    return <div className="App">
    <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1 className="App-title">Welcome to React</h1>
    </header>
    <ErrorBoundary>
        <Profile />
    </ErrorBoundary>
</div>
}
}

我看到功能组件在错误发生后仍然被调用并被捕获。任何人都可以解释为什么调用 render 函数。

不知道的请按照的回答,按esc键可以看到错误边界。

https://codesandbox.io/s/nn9kw2k3ql

这是一个工作示例,您需要按 esc

我输入了你的 Profile 没有做任何更改,它也按预期工作。

要清楚...

您可以单击 esc 的红色叠加层将在您进入生产设置后被删除。它们仅供开发使用。这就是为什么您要实施 errorBoundary 的原因,它在两种情况下都适用。

因此,如果您的代码在开发过程中出现错误,这两个错误都会出现。

如果您查看控制台,您会收到以下消息:

false // from ErrorBoundary this.state.error
i am here  // inside the potential error componenet
i am here  // inside the potential error componenet
The above error occurred in the <Profile> component: //from Error Boundary
true // from ErrorBoundary this.state. error

第一个 false 来自 ErrorBoundary,因为在初始加载时没有错误,所以它会尝试呈现 children,然后在子项中记录 i am here。并发现错误,并更新 errorboundary 组件。在那之后,你再也看不到 I am here,因为 errorboundary 开始并且不再渲染 children

为了让 errorBoundary 知道它的 children 中有一些错误,错误必须首先发生。否则它不知道。 JS是一个动态类型的语言,一切都需要在运行时间内发生。

我认为你的条件错误如下:

if (!hasError) {
        return <HasError />
    }

如果 hasError 为真,你想在这里显示错误,对吗?否则将呈现 Profile 组件。

而且 componentDidCatch 是在 react16 中构建的,所以如果渲染函数抛出任何错误,这个方法将被自动触发。

正如您在问题中提到的那样,按 Esc 会取消覆盖,您可以看到 ErrorBoundary 消息,并且覆盖的可见性仅限于开发环境。

您可以查看更多相关信息

但是为什么要执行render函数,你需要知道一旦执行了render函数并且你的代码抛出一个RuntimeError,那是唯一一次componentDidCatch 你的 ErrorBoundary 方法。 create-react-app 还具有一项功能,它可以侦听正在生成的 RuntimeErrors 并报告错误的根本原因,这就是您在叠加层中看到的内容。

查看生成Overlay的相关代码,可以查看这个github code

希望我能回答你的问题。