为什么React仍然使用错误边界渲染子组件

时间:2018-07-23 02:42:39

标签: reactjs react-16

我将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函数。 enter image description here

对于不认识的人,请遵循link的回答,您可以通过按键esc看到错误边界。

3 个答案:

答案 0 :(得分:0)

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是一种动态类型的lang,一切都需要在运行时发生。

答案 1 :(得分:0)

我认为您的情况如下:

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

如果hasError为true,您想在这里显示错误,对吗?否则将渲染Profile组件。

而且componentDidCatch也内置在react16中,因此,如果渲染函数抛出任何错误,此方法将自动触发。

答案 2 :(得分:0)

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

您可以查看有关此内容的更多信息 here

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

要检查生成叠加层的相关代码,可以选中此 github code

希望我能回答你的问题。